Skip to content

Commit

Permalink
Merge pull request #513 from vertigo-one/ansible-vcert-playbooks-example
Browse files Browse the repository at this point in the history
Add examples for running playbooks with ansible while using TLSPC SVC accounts
  • Loading branch information
JigarAtVenafi committed Sep 11, 2024
2 parents dd13540 + 336fe8b commit 13aee67
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 0 deletions.
64 changes: 64 additions & 0 deletions examples/ansible/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Ansible Playbooks to Run VCert Playbooks Against the Venafi Control Plane

This folder contains sample Ansible playbooks that can be used to trigger [VCert Playbooks](https://github.com/Venafi/vcert/blob/master/README-PLAYBOOK.md) using Venafi Control Plane (VCP) [Service Accounts](https://docs.venafi.cloud/vcs-platform/serviceaccounts/about-service-accounts/).

These ansible playbooks allow VCert playbooks to be executed without storing the credentials localy on the managed VMs. This is done by authentiating only once to your IDP on the ansible control node, and then executing a Vcert Playbook on each managed VM using the resulting temporary JSON Web Token (JWT) as the authentication credential to VCP. Ansible then injects the JWT into an environment variable that VCert will read when ansible executes the vcert playbook on the VM. Once VCert finishes running the shell session is closed, and the JWT is no longer avaliable on the VM. Additionally, this menthod allows the VM owners to control the VCert playbook if they so chose, however, it is possible for ansible to manage the VCert Playbook file if required.

**IDP support note:** If your IDP does not have an example ansible playbook that does not mean that it is impossible to use it. It only means that an example does not exist in this repository for it. The likely reason is lack of access or time to devote to learning the IDP. Contributions of ansible playbooks for other IDPs are welcome.

## Rquirements

Each Sample uses:
- A VCP [Custom API integration](https://docs.venafi.cloud/vcs-platform/serviceaccounts/c-about-custom-api-integration-sa/) Service Account
- A OAuth2.0 enabled application or OAuth API integration with an IDP that will return a [JSON Web Token (JWT)](https://jwt.io/)
- The OAuth 2.0 Client Credential authentication method for authenticating to the IDP Oauth2.0 endpoint.

Prior Work you must do before using these playbooks:
- VCert must be installed on all servers that you wish to run playbooks on.
- **Note:** the playbooks assume VCert is installed in your PATH. If it is not, you will need to edit the playbooks to contain the full path to the VCert binary.
- A VCP Custom API Intgration Service account already configured in TLSPC.
- An application or API integration must be configured in your IDP

Required Information - All playbooks
- The **Client ID** of your application in your IDP
- The **Client Secret** associated with your Client ID
- The **Oauth2.0 Token URL** of your IDP
- The **Path to the VCert Playbook file** that you wish to execute on your servers/inventory. This must be the complete, fully qualified, path and must be the same on all servers you wish to run it on.
- The [VCert Playbook](https://github.com/Venafi/vcert/blob/master/README-PLAYBOOK.md) should contain your SVC Account Token Url as the value for `tokenURL` inside of the `credentials` block in the playbook.
- An **ansible inventory** containing the servers you wish to run Vcert Playbooks on using this VCP service account.


## Playbook flow
```mermaid
---
title: Playbook Execution
---
%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart LR
subgraph Ansible_Control_Node
authenticate(Authenticate to IDP using OAuth 2.0 Client Credentials) --> JWT
end
subgraph Managed_Server
injectcredentials(Add JWT to environment as TLSPC_EXTERNAL_JWT)
runvcert(vcert run --file $Vcert_Playbook_Path)
injectcredentials --> runvcert
runvcert --> vcert
subgraph vcert
direction TB
vcpauth(Authenticate to VCP using JWT to get VCP access token)
reqestcert("Request certificate(s) from TLSPC using access token")
installcert("Install certificates(s) on machine")
postinstall(Run Post-installation actions if configured)
vcpauth --> reqestcert --> installcert --> postinstall
end
end
Start --> Ansible_Control_Node
Ansible_Control_Node --> Managed_Server
```

46 changes: 46 additions & 0 deletions examples/ansible/oauth2.ADFS_clientcredentials.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
- name: Authenticate to ADFS OAuth2.0 provider using Client Credentials Flow.
hosts: localhost
vars:
# The value of these variables are specific to the Application that is being automated.
# Each application or team should have a separate IDP application integration with separate credentials.
# Reuse of the same IDP integration across the entire company is not advised due to the access
# the Venafi service account will need to be given inside the TLSPC platform.
idp_token_url: <Your ADFS Token URL with https://>
idp_audience: <Your Audience value>
idp_client_id: <Your Client ID>
idp_client_secret: <Your Client Secret>

tasks:
- name: Authenticate to ADFS
ansible.builtin.uri:
url: '{{ idp_token_url }}'
method: POST
body_format: form-urlencoded
body:
# ADFS's Scope parameter is in format of <audience>/<scope> and provides both to the platform.
- [ scope, '{{ idp_audience }}/openid']
# A redirect URI is needed as ADFS uses it along with the Client_id to to determine which
# Application Group and Server Application you are authenticating as.
# It must match exactly what is in your application group.
- [ redirect_uri, "http://localhost"]
- [ client_id, '{{ idp_client_id }}' ]
- [ client_secret, '{{ idp_client_secret }}' ]
- [ grant_type, client_credentials ]
status_code: 200
register: auth

- name: Execute VCert Playbook on WebApp Servers
#hosts: my_app_servers
hosts: <My inventory>
vars:
# The fully qualified path to the Vcert Playbook file is stored here.
# This should be the same for all hosts in the chosen inventory.
vcert_playbook_path: <Vcert Playbook Fully Qualified Path>

tasks:
- name : Execute VCert playbook with JWT.
shell: vcert run --file '{{ vcert_playbook_path }}'
environment:
TLSPC_EXTERNAL_JWT: '{{ auth.json.access_token }}'

42 changes: 42 additions & 0 deletions examples/ansible/oauth2.Auth0_clientcredentials.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
- name: Authenticate to Auth0 OAuth2.0 provider using Client Credentials Flow.
hosts: localhost
vars:
# The value of these variables are specific to the Application that is being automated.
# Each application or team should have a separate IDP application integration with separate credentials.
# Reuse of the same IDP integration across the entire company is not advised due to the access
# the Venafi service account will need to be given inside the TLSPC platform.
idp_token_url: <Your Auth0 Token URL with https://>
idp_audience: <Your Audience value>
idp_client_id: <Your Client ID>
idp_client_secret: <Your Client Secret>

tasks:
- name: Authenticate to Auth0
ansible.builtin.uri:
url: '{{ idp_token_url }}'
method: POST
body_format: form-urlencoded
body:
- [ audience, '{{ idp_audience }}']
- [ scope, certificates:request ]
- [ client_id, '{{ idp_client_id }}' ]
- [ client_secret, '{{ idp_client_secret }}' ]
- [ grant_type, client_credentials ]
status_code: 200
register: auth

- name: Execute VCert Playbook on WebApp Servers
#hosts: my_app_servers
hosts: <My inventory>
vars:
# The fully qualified path to the Vcert Playbook file is stored here.
# This should be the same for all hosts in the chosen inventory.
vcert_playbook_path: <Vcert Playbook Fully Qualified Path>

tasks:
- name : Execute VCert playbook with JWT.
shell: vcert run --file '{{ vcert_playbook_path }}'
environment:
TLSPC_EXTERNAL_JWT: '{{ auth.json.access_token }}'

41 changes: 41 additions & 0 deletions examples/ansible/oauth2.AzureEntra_clientcredentials.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
- name: Authenticate to Azure Entra ID's OAuth2.0 provider using Client Credentials Flow.
hosts: localhost
vars:
# The value of these variables are specific to the Application that is being automated.
# Each application or team should have a separate IDP application integration with separate credentials.
# Reuse of the same IDP integration across the entire company is not advised due to the access
# the Venafi service account will need to be given inside the TLSPC platform.
idp_token_url: <Your Azure Entra ID Token URL with https://>
idp_client_id: <Your Client ID>
idp_client_secret: <Your Client Secret>

tasks:
- name: Authenticate to Azure Entra ID
ansible.builtin.uri:
url: '{{ idp_token_url }}'
method: POST
body_format: form-urlencoded
body:
# Azure Entra ID's scope parameter can be .default to get the default scope and can be much more complicated if you want it to be.
- [ scope, 'certificates:request']
- [ client_id, '{{ idp_client_id }}' ]
- [ client_secret, '{{ idp_client_secret }}' ]
- [ grant_type, client_credentials ]
status_code: 200
register: auth

- name: Execute VCert Playbook on WebApp Servers
#hosts: my_app_servers
hosts: <My inventory>
vars:
# The fully qualified path to the Vcert Playbook file is stored here.
# This should be the same for all hosts in the chosen inventory.
vcert_playbook_path: <Vcert Playbook Fully Qualified Path>

tasks:
- name : Execute VCert playbook with JWT.
shell: vcert run --file '{{ vcert_playbook_path }}'
environment:
TLSPC_EXTERNAL_JWT: '{{ auth.json.access_token }}'

28 changes: 28 additions & 0 deletions examples/ansible/testvcertplaybook.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
config:
connection:
platform: vaas
credentials:
tokenURL: <Your Service Account Token URL - Copy from VCP>
externalJWT: '{{ Env "TLSPC_EXTERNAL_JWT" }}'
certificateTasks:
- name: appcert
setEnvVars: #delete the environment variables that you do not need.
- "thumbprint" #VCERT_TASKNAME_THUMBPRINT
- "serial" #VCERT_TASKNAME_SERIAL
- "base64" #VCERT_TASKNAME_BASE64
renewBefore: 31d
request: #change the request parameters to fit your certificate needs.
csr: local
subject:
commonName: 'myapp.corp.net'
sanDNS:
- 'myapp.corp.net'
zone: "<myapp>\\<issuingtemplate>"
installations:
- format: PEM
file: "./cert.cer"
chainFile: "./chain.cer"
keyFile: "./key.pem"
backupFiles: false
#replace "TASKNAME" below with the name of the certificxate task that the after install action will run for. Example: VCERT_APPCERT_SERIAL
afterInstallAction: "echo $VCERT_TASKNAME_THUMBPRINT $VCERT_TASKNAME_SERIAL $VCERT_TASKNAME_BASE64"

0 comments on commit 13aee67

Please sign in to comment.