-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New Custom Resource: Certificate and Library: SecurityCommand #53
Conversation
- Split up smoke tests for easier testing
Use the security command to install a certificate Use 3 properties and a simple if else statement to differentiate between .cer and .p12 files
- Add new recipe installing dummy .p12 file
Add _test to file name
Use some functions that are modeled after the actual security command such as unlock-keychain, add-certificates, and import. There is also a install_certificate wrapper that wraps the import and add-certificate commands to hide the differences of .p12 and .cer file installation from the user.
libraries/security_cmd.rb
Outdated
[@security, 'unlock-keychain', '-p', kc_passwd] | ||
end | ||
|
||
def add_certificates |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use a ternary statement here in the interest of brevity:
@keychain == '' ? [@security, 'add-certificates', @cert] : [@security, 'add-certificates', @cert, '-k', @keychain]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
property :keychain, String | ||
|
||
action_class do | ||
def keychain |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ternary statement here as well:
property_is_set?(:keychain) ? new_resource.keychain : ''
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
resources/certificate.rb
Outdated
test = SecurityCommand.new(new_resource.certfile, keychain) | ||
|
||
execute 'unlock keychain' do | ||
command [*test.unlock_keychain('vagrant')] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's change 'vagrant'
to node['macos']['admin_user']
attribute; just in case someones uses a different username in their environment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
resources/certificate.rb
Outdated
end | ||
|
||
action :install do | ||
test = SecurityCommand.new(new_resource.certfile, keychain) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can use a better name than test
here: perhaps certificate
or resource_cert
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
libraries/security_cmd.rb
Outdated
end | ||
|
||
def install_certificate(cert_passwd) | ||
if ::File.extname(@cert) == '.p12' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the X.509 standard, there are a few different file extensions used for the various types of files. For certificates, we might find them with .der
, .crt
, or .cer
and for PKCS #12 files, we might find them with .p12
of pfx
.
Might it make sense to check for these possible variations? Could we test for that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'import' command can actually support the formats: openssl, bsafe, raw, pkcs7, pkcs8, pkcs12, x509, openssh1, openssh2, and pemseq. We can probably make an array of acceptable file formats and check against those.
libraries/security_cmd.rb
Outdated
elsif ::File.extname(@cert) == '.cer' | ||
add_certificates | ||
else | ||
Chef::Exception.fatal('invalid cert file') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the interest of informative exceptions, let's include the certificate in the exception message. Maybe something like this?
Chef::Exception.fatal("Invalid certificate: #{@cert}. We looked in the #{@keychain} keychain. Double-check the integrity of both the certificate and the keychain.")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
resources/certificate.rb
Outdated
@@ -0,0 +1,28 @@ | |||
resource_name :certificate | |||
default_action :install |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there is only one action, we don't need to indicate a default. If we decide to add more actions later, then we'll need to add it. I would probably remove it until then, but it's up to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
describe MacOS::SecurityCommand do | ||
context 'when SecurityCommand object is instantiated' do | ||
it 'security should use /usr/bin/security' do | ||
test = MacOS::SecurityCommand.new('/Users/vagrant/Test.p12', '') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to instantiate this object for every test. Let's use let
to create these objects, as well as some more descriptive names for the ones that get used:
describe MacOS::SecurityCommand do
let(:p12_cert) { MacOS::SecurityCommand.new('/Users/vagrant/Test.p12', '') }
context 'when a SecurityCommand object is instantiated' do
it 'security should use /usr/bin/security' do
expect(p12_cert.security).to eq '/usr/bin/security'
end
end
end
From betterspecs.org
:
When you have to assign a variable instead of using a before block to create an instance variable, use
let
. Usinglet
the variable lazy loads only when it is used the first time in the test and get cached until that specific test is finished.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
libraries/security_cmd.rb
Outdated
class SecurityCommand | ||
attr_reader :cert | ||
attr_reader :keychain | ||
attr_reader :security |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this attribute is the path to the command, let's indicate that with the name. Something like :security_executable
, :security_command
or :security_cmd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
- Use ternary statements - Change vagrant password - Rename created certificate object for testing - Support more file types by putting them in an array before calling add or import - Use more informative exception
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work here @mjmerin - thanks to @americanhanko as well for the good feedback.
I'm excited to see what this looks like when paired with a keychain resource!
This merge contains hotfixes
This pull request fixes Issue #50. Rather than create a security resource, the task was split up to create a security back end to drive other resources such as a certificate and even a keychain resource.
SecurityCommand Library
Basic library intended to encapsulate some features of the security command. As of now this will allow you to unlock a keychain, and add a certificate of the .p12 or .cer format.
Certificate Custom Resource
This is a new custom resource that utilizes the SecurityCommand library mentioned above as its backend. It currently only has 3 properties for basic certificate install.
Notes