top of page
Search

Infrastructure as Code and how we can improve on the use of shared secrets

Updated: May 10, 2023


Infrastructure as code (IaC) is the practice of managing and provisioning computer data centers through machine-readable definition files, rather than physical hardware configuration or interactive configuration tools. Infrastructure as code is a key component of DevOps, which is a set of practices that combines software development (Dev) and IT operations (Ops).


IaC has a number of benefits, including:

  • Improved reliability: IaC can help to improve the reliability of infrastructure by making it easier to reproduce and manage configurations.

  • Increased efficiency: IaC can help to increase the efficiency of infrastructure management by automating repetitive tasks.

  • Reduced costs: IaC can help to reduce the costs of infrastructure management by making it easier to scale and deploy infrastructure.

  • Improved security: IaC can help to improve the security of infrastructure by making it easier to track and manage changes to configurations.

There are a number of different IaC tools available, including:

  • Ansible: Ansible is an open-source automation platform that can be used to configure and manage infrastructure.

  • Chef: Chef is a commercial automation platform that can be used to configure and manage infrastructure.

  • Puppet: Puppet is a commercial automation platform that can be used to configure and manage infrastructure.

  • Terraform: Terraform is an open-source infrastructure as code software tool that enables users to safely and predictably create, change, and improve infrastructure.

Authentication and authorization with these tools can be wildly different. Let's take Ansible as an example Ansible is an open-source automation platform that can be used to configure and manage systems and applications. Ansible can use a few different authentication methods to secure access to managed systems, with the most common being password authentication. To use password authentication, specify the username and password of the user that Ansible will use to connect to the managed system. That's done in the Ansible configuration file or on the command line.


Ansible also supports public key authentication. To use public key authentication, you must create a public/private key pair and upload the public key to the managed system. You can then specify the path to the private key in the Ansible configuration file or on the command line. Ansible also supports other authentication methods, such as LDAP authentication and Windows integrated authentication.


Here is an example of how to specify the username and password in the Ansible configuration file:

[defaults]
remote_user = my_user
password = my_password

As you can see, it's just right there. Arguably, if someone can see it, you have bigger problems. They then log in to do a task using a command like this:

ansible my_host -u my_user -p my_password

Now there's not just a credential in the clear in a config file, but there's one in the bash history on a client computer. Public key authentication is a more secure authentication method than password authentication. To use public key authentication, you must create a public/private key pair and upload the public key to the managed system. You can then specify the path to the private key in the Ansible configuration file or on the command line.


To create a public/private key pair, the ssh-keygen command will create a public/private key pair in the current directory. The public key will be named id_rsa.pub and the private key will be named id_rsa. Once you have created the public/private key pair, you must upload the public key to the managed system. You can do this using the ssh-copy-id command, as follows:

ssh-copy-id my_user@my_host

This is more secure. The public key is then uploaded to the ~/.ssh/authorized_keys file on the managed system and you can specify the path to the private key in the Ansible configuration file or on the command line, with the edit in the config file looking like this:

[defaults]
private_key_file = ~/.ssh/id_rsa

Now, the machine is able to initiate a flow. Ansible workflows are a powerful way to automate complex tasks. They're made up of a series of tasks that are executed in a specific order. Tasks can be anything from running a command to calling a function or deep link in an app. Playbooks define workflows. A playbook is a YAML file that contains the tasks and the order in which they should be executed.


Once you have created a playbook, you can run it using the ansible-playbook command. The ansible-playbook command takes the name of the playbook as its only argument. For example, to run the playbook my_playbook.yml, you would use the following command:

ansible-playbook my_playbook.yml

Ansible will execute the tasks in the playbook in the order in which they are defined. If a task fails, Ansible will continue to execute the remaining tasks in the playbook.

If you want Ansible to stop executing the playbook if a task fails, you can use the -e option to specify the fail_on_error option. For example, to stop executing the playbook if a task fails, you would use the following command:

ansible-playbook -e fail_on_error=yes my_playbook.yml

Consider the following when building those playbooks in ansible (or the same types of workflows in similar tooling):

  • Use descriptive names for tasks. This makes it easier to understand what each task does.

  • Use comments in playbooks to explain what each task does (like commenting code). This will make it easier to understand your playbooks and to troubleshoot problems.

  • Use variables in playbooks to make them reusable. For example, to define the hosts to run the playbook against (we use this a lot for automated functional testing on different versions of macOS).

  • Use tags to group related tasks together (e.g. tasks that deploy a given web application together).

  • Use roles to organize tasks. (e.g. create a role to deploy the web application && another to configure the database or deploy any necessary keys).

Now, there are similarities between Chef, Puppet, and Terraform. Admins can define these flows and then configure a tool like git so they can check in a change and trigger changes to the flow. But now we get to the point where these are all run through git in a way. Yet, someone has the git credentials. This might be an app deployment to the Apple App Stores. Someone has the key. And given that the passwords and the keys can be copies into iCloud Keychain and then exported from there on other machines, we can kinda' end-around all the things we just spent countless hours putting into place. In other words, this kind of workflow automation is awesome for a lot of uses - but what I really want is a level of non-repudiation that "I couldn't have been the one that deployed the build that blew up the interwebs."


That's why we built multi-party password sharing and escrow. Here, we can just-in-time provision the necessary assets for an Ansible, Chef, Xcode, or whatever flow and define which users are required to unlock the flow. When prompted, all they have to do is provide a biometric credential and their devices are able to get to all the things. Like all of them that you decide. This may require a little webhook and script-bit stringing together here and there, 'cause the one thing we've learned about gitops and continual devlops is that basically no two orgs do things the same. Therefore, might as well build an API and webhooks on it all for those who know what they need to know - rather than please like 5 people and annoy the rest.


To see what we've built and work with us to make it better, please feel free to check out our private beta. I'm sure if you were insulted by how poorly our ansible walkthrough was, that we'd be so very lucky to have you on our side!


4 views0 comments

Recent Posts

See All
bottom of page