Chef: Jenkins cookbook recipe for enabling security - security

I am currently using the Chef supermarket Jenkins cookbook to deploy an instance of Jenkins. I am attempting to enable security in my configuration of the jenkins instance in the _master_war_.rb recipe file. Code to enable security and create a user using an RSA key is below:
require 'openssl'
require 'net/ssh'
unless node.run_state[:jenkins_private_key]
# defaults to /etc/chef-jenkins-api.key
key_path = node['jenkins_chefci']['jenkins_private_key_path']
begin
Chef::Log.info 'Trying to read private key from ' + key_path + ' for the chef user in jenkins'
key = OpenSSL::PKey::RSA.new File.read(key_path)
Chef::Log.info 'Successfully read existing private key'
rescue
key = OpenSSL::PKey::RSA.new 2048
Chef::Log.info 'Generating new key pair for the chef user in jenkins in ' + key_path
file key_path do
content key.to_pem
mode 0500
sensitive true
end
end
public_key = [key.ssh_type, [key.to_blob].pack('m0'), 'auto-generated key'].join(' ')
# Create the Jenkins user with the public key
jenkins_user 'chef' do
id 'chef#' + Chef::Config[:node_name]
full_name 'Chef Client'
public_keys [public_key]
end
# Set the private key on the Jenkins executor
node.run_state[:jenkins_private_key] = key.to_pem
end
When I attempt to apply this recipe in a run list on a managed node, I receive the following error:
NoMethodError
-------------
undefined method `[]' for nil:NilClass
The stacktrace indicates that the error is related to this particular line of code from my recipe file:
>> key_path = node['jenkins_chefci']['jenkins_private_key_path']
I have seen this error (undefined method `[]' for nil:NilClass), quite a bit online, however have not been able to narrow down the root cause in my recipe. Could I be missing something in my recipe file? I'm wondering if the root cause of the error could be related to these couple lines:
require 'openssl'
require 'net/ssh'

Related

How to run aspnet_regiis.exe in a deferred custom action and pass the value of INSTALLDIR property?

I have a custom action (RunEncryption2) that I'm using for encrypting a configuration file by using aspnet_regiis.exe. The custom action type that I'm using is an EXE with path referencing a directory (initial type 34) using deferred execution in system context (so the final type is 3106). The file that I want to encrypt is on INSTALLDIR, so I have a Set Property custom action (SetRunEncryption2, type 51) where I'm setting RunEncryption2=[INSTALLDIR]. My two custom actions look like this:
SetRunEncryption2
Property Name: RunEncryption2
Property Value: [INSTALLDIR]
RunEncryption2
Working Directory: WindowsFolder
File Name & Command line: [WindowsFolder]Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pef "connectionStrings" "[CustomActionData]" -prov "DataProtectionConfigurationProvider"
When the installer runs, I get no error, however the file gets no encryption at all. When I review the log, I get the following:
MSI (s) (34:C0) [17:32:11:356]: Executing op: CustomActionSchedule(Action=RunEncryption2,ActionType=3106,Source=C:\WINDOWS\,Target=C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pef "connectionStrings" "" -prov "DataProtectionConfigurationProvider",CustomActionData=C:\Test\)
From the log I can see that the CustomActionData property has been set correctly, however it hasn't been included as part of the command.
At this point the only way I have to make the command work is passing a hard-coded value of INSTALLDIR, otherwise it doesn't seem to work.
I have tried:
Not using CustomActionData, instead passing the value of INSTALLDIR as part of my command line directly.
Using a "Path in Property value" custom action with similar results.
When I run option 1 above, I get a 1722 error on the log:
MSI (s) (C4:50) [12:49:46:968]: Note: 1: 1722 2: RunEncryption2 3: C:\WINDOWS\ 4: C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pef "connectionStrings" "C:\Test\" -prov "DataProtectionConfigurationProvider"
Error 1722. There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support personnel or package vendor. Action RunEncryption2, location: C:\WINDOWS\, command: C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pef "connectionStrings" "C:\Test\" -prov "DataProtectionConfigurationProvider"
MSI (s) (C4:50) [12:49:56:841]: Product: TestEncryption -- Error 1722. There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support personnel or package vendor. Action RunEncryption2, location: C:\WINDOWS\, command: C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pef "connectionStrings" "C:\Test\" -prov "DataProtectionConfigurationProvider"
Does anyone know how can I do to correctly execute this command and dynamically pass the value of INSTALLDIR?
Finally found the problem was not in the custom action passing the properties, but in the way that aspnet_iisreg is expecting the parameters.
INSTALLDIR is passing the string with a trailing slash (e. gr. c:\Test\), when I hard coded the installation path I was passing c:\Test instead.
The solution consisted in creating another custom action that removes the trailing slash and stores the value in a new property, this then can be used as parameter for aspnet_iisreg.
By the way, as Michael Urman mentioned, there was no need to use CustomActionData. Thanks.

Registry tab does not work

I have installed gitlab on AWS server and it is working as expected.
http://ec2-54-167-34-63.compute-1.amazonaws.com/
But when I click on "Registry" tab, I am shown page not found error (500)
The relevant part from /etc/gitlab/gitlab.rb
gitlab_rails['gitlab_default_projects_features_container_registry'] = true
# registry_external_url 'https://registry.gitlab.example.com'
registry_external_url 'http://ec2-54-167-34-63.compute-1.amazonaws.com:4567'
# Settings used by GitLab application
gitlab_rails['registry_enabled'] = true
gitlab_rails['registry_host'] = "http://ec2-54-167-34-63.compute-1.amazonaws.com"
gitlab_rails['registry_port'] = "5005"
gitlab_rails['registry_api_url'] = "http://localhost:5000"
gitlab_rails['registry_key_path'] = "/var/opt/gitlab/gitlab-rails/certificate.key"
gitlab_rails['registry_path'] = "/var/opt/gitlab/gitlab-rails/shared/registry"
gitlab_rails['registry_issuer'] = "omnibus-gitlab-issuer"
# Settings used by Registry application
registry['enable'] = true
registry['username'] = "registry"
registry['group'] = "registry"
registry['uid'] = nil
registry['gid'] = nil
registry['dir'] = "/var/opt/gitlab/registry"
registry['log_directory'] = "/var/log/gitlab/registry"
registry['log_level'] = "info"
registry['rootcertbundle'] = "/var/opt/gitlab/registry/certificate.crt"
registry['storage_delete_enabled'] = true
Update
As per the logs below, I need gitlab-registry.key file in the correct location. What is this file and how do I generate one?
tail /var/log/gitlab/gitlab-rails/production.log
Started GET "/root/test/container_registry" for 125.99.49.46 at 2016-10-24 08:29:27 +0000
Processing by Projects::ContainerRegistryController#index as HTML
Parameters: {"namespace_id"=>"root", "project_id"=>"test"}
Completed 500 Internal Server Error in 23ms (ActiveRecord: 3.5ms)
Errno::ENOENT (No such file or directory # rb_sysopen - /var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key):
lib/json_web_token/rsa_token.rb:20:in `read'
lib/json_web_token/rsa_token.rb:20:in `key_data'
lib/json_web_token/rsa_token.rb:24:in `key'
lib/json_web_token/rsa_token.rb:28:in `public_key'
lib/json_web_token/rsa_token.rb:33:in `kid'
lib/json_web_token/rsa_token.rb:12:in `encoded'
app/services/auth/container_registry_authentication_service.rb:30:in `full_access_token'
app/models/project.rb:421:in `container_registry_repository'
app/controllers/projects/container_registry_controller.rb:28:in `container_registry_repository'
app/controllers/projects/container_registry_controller.rb:8:in `index'
lib/gitlab/request_profiler/middleware.rb:15:in `call'
lib/gitlab/middleware/go.rb:16:in `call'
Update 2
I guess I need to generate a certificate as explained here...
http://www.bonusbits.com/wiki/HowTo:Setup_HTTPS_for_Gitlab
Check the GitLab server log (since it is an error 500. Example of such logs: issue 23019)
There is an issue pending with GitLab 8.13: 23575: No way to enable container registry, with a merge request 7037: Fix typo in project settings that prevents users from enabling container registry.
They might be related with your issue.
Issue 23339 mentions also "sorting out self signed certs problem (my registry is under different domain than gitlab itself)": that should not be the case here.
Issue 23181 (Pushing to Registry Still Frequently Encounters unauthorized: authentication required) suggests that the error is gone ofr docker 1.11+ (so it depends on which version of docker you are using on AWS)
Regarding gitlab-registry.key mentioned by the OP's edit, it should be created by a simple reconfigure, if declared properly.
So double-check:
1316
It turns out it was a typo on my part.
The config key is registry_nginx["ssl_certificate"] not registry_nginx[ssl_certificate].
1218 and merge request 3787 which show how this feature was added.
Try to set only few of the registry settings like :
registry_external_url 'http://ec2-54-167-34-63.compute1.amazonaws.com:4567'
Don't set the gitlab_rail['registry'] and registry['xxxxx'] if you want to keep the default values, and don't set values if you don't know what you are modifying.
About the certificates, check at the very bottom of the gitlab.rb file, and here you can set your certificates for the registry:
registry_nginx['ssl_certificate'] = "/path/to/my/cert.crt"
registry_nginx['ssl_certificate_key'] = "/path/to/my/key.key"
Also check the output of this commands to make a check of your GitLab instance:
sudo gitlab-rake gitlab:check
Just like deporclick did, Set your certificates for the registry as:
registry_nginx['ssl_certificate'] = "/path/to/my/cert.crt"
registry_nginx['ssl_certificate_key'] = "/path/to/my/key.key"

Foreman Multiline ENV Variable Error

I am trying to pass the contents of my pem file as a string in my .env file using \n to translate the form in the pem file to be used in an ENV variable. The issue, however, is that I'm getting an error from this variable and I'm not sure what it means, but I saw where there was an issue closed allowing for multiline so I'm not sure why this error exists.
Here is my terminal command nf run nodemon app.js
Here is the version 1.4.1
Here is the format of my pem file set within my .env file:
CF_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n
MIIEpAIBAAKCAQEAm7NA5731034RiKsEkuBTrkoBidwFD7hsdfaiohdsfahsdfL99Iw5R4uTA\n
jpPJTOUHTJNMSNF472h42ofnlNflnriNBTPOHNJFRPNSRPFNSRpfPRNFORNFPRSNFpSNFFPNf\n
-----END RSA PRIVATE KEY-----"
This is the error message:
/Users/user/.nvm/versions/node/v4.3.2/lib/node_modules/foreman/lib/envs.js:38
case '"': return /^"([^"]*)"/.exec(val)[1];
^
TypeError: Cannot read property '1' of null
at parseValue (/Users/user/.nvm/versions/node/v4.3.2/lib/node_modules/foreman/lib/envs.js:38:46)
I don't think that it can work like that. It seems that node foreman scans the file line by line and it is trying to create key-value pairs and seems that is not aware of \n or other methods that can split the line. I don't think that you have to put it on more lines, though. Possibly you can do something like that:
CF_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAm7NA57......\n...."
and it is quite possible that will not work. Why don't you put just the filename in the env vars? Something like:
CF_PRIVATE_KEY_FILENAME="my-file-id-rsa"
and when you boot the application:
var id_rsa_contents = fs.readFileSync(__dirname + proces.env.CF_PRIVATE_KEY_FILENAME);

Why Chef do not find my files?

I'm developing a Ganglia recipe in Chef.
Is very simple, I build four different configurations files, I already tried to use as template, but to keep it simple, I build these configuration files.
This is my recipe:
return if tagged?('norun::ganglia')
case node[:platform]
when "ubuntu", "debian"
pkg = "ganglia-monitor"
when "redhat", "centos", "fedora"
pkg = "ganglia-gmond"
end
package "#{pkg}" do
action :install
end
cookbook_file "/etc/ganglia/gmond.conf" do
owner "root"
group "root"
mode "0644"
source "gmond/" + node['base']['dc'] + "/node/gmond.conf"
end
# Adding ganglia-gmond as service
service "gmond" do
supports :status => true,
:restart => true
action [ :enable, :start ]
end
And this is how my recipe is structured:
cookbooks/ganglia/
cookbooks/ganglia/files/default/gmond/* // I have others sub-folders here too
cookbooks/ganglia/files/default/gmond/diveo/node/gmond.conf
cookbooks/ganglia/recipes/default.rb
But when I tried to run my recipe, it gives the follow error:
[2013-05-14T14:23:38+00:00] FATAL: Chef::Exceptions::FileNotFound: cookbook_file[/etc/ganglia/gmond.conf] (ganglia::default line 25) had an error: Chef::Exceptions::FileNotFound: Cookbook 'ganglia' (0.1.0) does not contain a file at any of these locations:
files/centos-5.7/gmond/diveo/node/gmond.conf
files/centos/gmond/diveo/node/gmond.conf
files/default/gmond/diveo/node/gmond.conf
This cookbook _does_ contain: ['diveo/monitor/gmond.conf','diveo/node/gmond.conf','awsvir/monitor/gmond.conf','awsvir/node/gmond.conf','awssp/monitor/gmond.conf','awssp/node/gmond.conf','alog/monitor/gmond.conf','alog/node/gmond.conf']
Basically it says that I not have the file, but I do, in the right path, right ?
If node['base']['dc'] is a platform name, then cookbook_file statement should look like
cookbook_file "/etc/ganglia/gmond.conf" do
owner "root"
group "root"
mode "0644"
source "gmond.conf"
end
and structure of your conf files should be like that
cookbooks/ganglia/
cookbooks/ganglia/files/default/gmond.conf
cookbooks/ganglia/files/centos-5.7/gmond.conf
...
And a little advice - use template instead of cookbook_file. One day you'll want to add some parameters to your gmane.conf anyway.
Also, here is a cookbook_file doc page from opscode.com -

Puppet breaks with multiple node inheritances

Puppet on the tst-01 works fine when using:
node "tst-01" inherits basenode {
But it breaks when I try to organize servers into groups with this configuration:
node "tst-01" inherits redhat6server {
The error with "inherits redhat6server" is:
err: Could not retrieve catalog; skipping run
[root#tst-01 ~]# puppet agent --test
err: Could not retrieve catalog from remote server: Error 400 on SERVER: Failed to parse template ldap/access.conf: Could not find value for 'netgroup' at 124:/etc/puppet/modules/ldap/templates/access.conf at /etc/puppet/modules/ldap/manifests/init.pp:82 on node tst-01.tst.it.test.com
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run
This is the access.conf file, that works fine if inherits is set to "inherits basenode".
[root#puppet]# grep -v "#" /etc/puppet/modules/ldap/templates/access.conf
+ : root : LOCAL
+ : #<%= netgroup %> : ALL
- : ALL : ALL
[root#puppet]#
This is the configuration in /etc/puppet/manifests/nodes.pp.
# Basenode configuration
node "basenode" {
include resolv_conf
include sshd
include ntpd
include motd
}
# Groups
node "redhat6server" inherits basenode {
include ldap_auth
}
# Testservers
node "tst-01" inherits redhat6server {
$netgroup = tst-01
}
I am planning to bring more organisation (read: avoid configuration repetition) in the nodes.pp by grouping machines, e.g. RH5 and RH6 machines instead of adding multiple lines of includes for all RH5 and RH6 servers.
Your running into a variable scoping problem. The official documentation discusses this issue.
In short, redhat6server doesn't have access to the netgroup variable.
The method I employ to work around this is to use hiera. With this, the ldap_auth module can be defined this way, and it will pull the value from a hiera configuration file (typically a yaml file in /etc/puppet/hiera).
You would defined ldap_auth like this:
ldap_auth/manifests/init.pp:
class ldap_auth($netgroup=hiera('netgroup')) {
...
}
Or if your on puppet 3.x, you can use automatic parameter lookup:
class ldap_auth($netgroup) {
...
}
And have a yaml file with:
ldap_auth::netgroup = 'netgroup'

Resources