Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
kgilpin committed Sep 3, 2014
0 parents commit 3ae2463
Show file tree
Hide file tree
Showing 6 changed files with 230 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .project
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>conjur-cookbooks-host-identity-chef</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.aptana.ide.core.unifiedBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.aptana.ruby.core.rubynature</nature>
<nature>com.aptana.projects.webnature</nature>
</natures>
</projectDescription>
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
= Description

Creates and installs Conjur host identity using Chef attributes and the Conjur
[host factory](http://developer.conjur.net/reference/services/host_factory).

## Attributes

See the Chef metadata.rb for detailed information about the attributes used by this recipe.

Basically, you should populate attributes which configure the connection to Conjur:

* appliance URL
* organization account name
* SSL certificate

You also need to provide two other pieces of information:

* A host factory token.
* The id of the host. You can use some data from OHAI (such as the AWS instance id), or the Chef node name,
or whatever you like. But it needs to be unique across your Conjur system.

## Conjur gem installation

The Conjur API and Conjur CLI gems are installed using by [chef_gem](https://docs.getchef.com/resource_chef_gem.html).
Therefore they can be used in any other subsequent cookbook as well.

## Conjur configuration

This cookbook builds `/etc/conjur.conf` from the Conjur connection information. This will be used
by all the downstream Conjur functionality.

File permissions are `0644`.

## Conjur host identity

Next, this cookbook looks for a host identity in `/etc/conjur.identity`. If that file exists, it's left intact.

If it doesn't exist, the host factory token is used to create a new host identity, which is then saved to the file.
File permissions are `0600`.

The `netrc_path` entry in `conjur.conf` points to `/etc/conjur.identity`. Therefore, downstream Conjur tools such as the
Conjur CLI will automatically pick up the host identity from this file and use it.

# Testing

Once the cookbook has run, you can verify the host identity by running `conjur authn whoami`. For example:

# /opt/chef/embedded/bin/conjur authn whoami
{"account":"demo","username":"host/kgilpin@spudling.local/chef-tutorial-1-0/vagrant/ff849c12-95d7-4720-9fb7-2c2be88582f7"}

In downstream processes, you can rely on the Conjur API and CLI being installed as Chef gems.
4 changes: 4 additions & 0 deletions attributes/default.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
default['conjur'] ||= {}

default['conjur']['configuration_file'] = '/etc/conjur.conf'
default['conjur']['configuration']['netrc_path'] = '/etc/conjur.identity'
62 changes: 62 additions & 0 deletions libraries/conjur_host_identity_chef.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
module ConjurHostIdentityChef
module ConjurHelper
extend self

def config_file node
node.conjur.configuration_file
end

def netrc_file
require 'conjur/config'
Conjur::Config[:netrc_path]
end

def config? node
File.exists?(config_file node)
end

def configure! node
require 'conjur/api'
require 'conjur/config'
require 'conjur/authn'

Conjur::Config.load [ config_file(node) ]
Conjur::Config.apply
end

# Updates the Conjur configuration. Yields the existing config (which may be an
# empty hash), then writes the config to the proper location.
def update_config node, &block
c = if config?(node)
config(node)
else
{}
end
yield c
File.write(config_file(node), YAML.dump(c))
end

def config node
YAML.load(File.read(config_file(node)))
end

def save_credentials credentials
require 'conjur/authn'
netrc = Conjur::Authn.netrc
netrc[Conjur::Authn.host] = credentials
netrc.save
end

def credentials?
require 'conjur/authn'
Conjur::Authn.get_credentials noask: true
true
rescue
false
end
end
end

class Chef::Recipe
include ConjurHostIdentityChef
end
31 changes: 31 additions & 0 deletions metadata.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name 'conjur-client'
maintainer 'Conjur, Inc.'
maintainer_email 'kgilpin@conjur.net'
license 'MIT'
description 'Obtains and istalls the Conjur host identity from Chef attributes'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '0.3.0'

attribute "conjur/host_factory_token",
description: "Conjur host factory token used to create the host identity.",
required: "required"
attribute "conjur/host_identity/id",
description: "Identity which will be assigned to the new host.",
required: "required"
attribute "conjur/configuration/appliance_url",
description: "URL of the Conjur service, for example https://conjur/api.",
required: "required"
attribute "conjur/configuration/account",
description: "Conjur organization account name",
required: "required"
attribute "conjur/configuration/ssl_certificate",
description: %Q{SSL certificate of the Conjur service. Substitute line breaks with the \n newline character.},
required: "required"
attribute "conjur/configuration_file",
description: "Alternate location for the Conjur configuration file. Default is /etc/conjur.conf"
attribute "conjur/configuration/netrc_path",
description: "Alternate location for the Conjur login cache. Default is /etc/conjur.identity"

%w(debian ubuntu centos fedora).each do |platform|
supports platform
end
64 changes: 64 additions & 0 deletions recipes/default.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#
# Copyright 2014, Kevin Gilpin
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# Alternatively, package 'ruby-devel'
package 'ruby-json'

chef_gem 'conjur-cli'
chef_gem 'conjur-asset-host-factory'

appliance_url = node.conjur.configuration.appliance_url
account = node.conjur.configuration.account
netrc_path = node.conjur.configuration.netrc_path

ConjurHelper.update_config(node) do |conjur_config|
conjur_config['appliance_url'] = appliance_url
conjur_config['account'] = account
conjur_config['netrc_path'] = netrc_path
end

# Store the Conjur SSL certificate, if it's available.
if node.conjur.configuration['ssl_certificate']
require 'fileutils'
cert_file = "/etc/conjur-#{account}.pem"
File.write(cert_file, node.conjur.configuration.ssl_certificate)
File.chmod 0644, cert_file
ConjurHelper.update_config(node) do |conjur_config|
conjur_config['cert_file'] = cert_file
end
end

# Configure the Conjur client using the config we've just written.
ConjurHelper.configure! node

# Create the host identity if it doesn't exist.
unless ConjurHelper.credentials?
require 'uri'
require 'conjur-asset-host-factory'

Chef::Log.debug "Conjur host identity not found in #{ConjurHelper.netrc_file}"

token = node.conjur.host_factory_token
host_id = node.conjur.host_identity.id

Chef::Log.info "Creating Conjur host identity '#{host_id}'"

host = Conjur::API.host_factory_create_host token, host_id

ConjurHelper.save_credentials [ "host/#{host['id']}", host['api_key'] ]
else
Chef::Log.debug "Conjur host identity already exists in #{ConjurHelper.netrc_file}"
end

0 comments on commit 3ae2463

Please sign in to comment.