Skip to content
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

Feature: Multiple credential types #8

Merged
merged 48 commits into from Nov 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
afb0344
Feature: Multiple credential types
Aug 5, 2019
aa87aed
WIP playing with credential proxy strategy
Aug 9, 2019
459a9c5
WIP progress with the type auto-sensing strategy
Aug 14, 2019
b31de0a
WIP remove some unneeded code
Aug 14, 2019
86f0096
WIP add happy-path tests for different credential types
Aug 20, 2019
e71b15a
WIP Add SSH key happy path test
Aug 20, 2019
99e2054
WIP update README examples
Aug 20, 2019
b9bb776
Add certificate credential happy path test
Aug 21, 2019
7d27156
Fix secret text example in readme
Aug 21, 2019
de667ca
Fully test the certificate round-trip in shouldSupportCertificateSecr…
Aug 22, 2019
654e346
Test SSH private key supports PCKS1 and PKCS8 in PEM format
Aug 22, 2019
11b706c
WIP chase NPE on Jenkins build
Aug 22, 2019
b17509c
Keep chasing that JDK9 KeyStore password handling change
Aug 22, 2019
393b4ca
Some tidy up
Aug 23, 2019
7173b88
javadoc fix
Aug 23, 2019
9746bd3
Unofficially test equivalence of SSH private key creds with string cr…
Aug 23, 2019
5bb038e
Filter out secret tags with null keys or null values
Aug 27, 2019
97d9aa4
WIP defend against the AWS tags property itself being null
Aug 27, 2019
3db88dc
Add failing test for new OpenSSH format private keys
Aug 29, 2019
baab04c
Add basic support for OpenSSH private keys
Sep 2, 2019
97bf38c
Update readme
Sep 3, 2019
f52c7c9
Refactor out ssh key validator for more robust unit tests
Sep 6, 2019
70011a5
Test some more 'unhappy path' edge cases
Sep 9, 2019
6da9842
Switch to tagging convention of jenkins:credentials:<key>
Sep 9, 2019
6a3b0d6
Try a fix for credentials naming issue
Sep 13, 2019
7b3a412
Clarify that the certificate store should be in PKCS12 format (JKS is…
Sep 13, 2019
ee514d2
WIP add withCredentials and environment pipeline tests (unfortunately…
Sep 24, 2019
2cfdcae
Clarify what should happen when binding all types of credentials in t…
Sep 26, 2019
a6b1dc6
Simplify project structure
Sep 26, 2019
b5ff658
Test another informal credential type equivalence
Sep 26, 2019
ff28448
WIP fix for environment binding scenario
Sep 30, 2019
c83c18c
Make binding component optional to let plugin load without pipeline-m…
Oct 1, 2019
d87205d
Only use a binding handler, not a custom binder, because a custom bin…
Oct 1, 2019
8bc49b0
Disable UI-based config tests (which pipeline-model-definition breaks…
Oct 2, 2019
da92087
Add basic (non-optimised) support for username/password cred binding …
Oct 7, 2019
ee61c95
Bump dependencies to versions that handle Java 11
Oct 7, 2019
0612d3f
Re-enable SSH private key cred bindings now we have upgraded the pipe…
Oct 7, 2019
b9ba716
Update documentation to reflect new capabilities
Oct 8, 2019
4ddf6cd
Update certificate example in README
Oct 8, 2019
8722f79
Noddy rebuild commit (ci.jenkins.io crashed yet again)
Oct 8, 2019
f546f52
Stop the AwsCredentials internal AWS client object becoming null in m…
Oct 9, 2019
d31d5fa
Create self-contained credential objects in custom CredentialsSnapsho…
Oct 15, 2019
a5958bd
No need to change failsafe report location now
Oct 16, 2019
851e47d
Do not trap NPEs in SSHKeyValidator when input is null
Oct 21, 2019
1529bc9
Write AWS exceptions to Jenkins logs when secret retrieval fails
Oct 23, 2019
1d3ffe0
Checkstyle fixes
Oct 24, 2019
a68d656
Throw IllegalStateException if secret contains neither a secretString…
Oct 28, 2019
cbf42d7
Add AWS machine auth and cross-account notes to README
Nov 4, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
143 changes: 121 additions & 22 deletions docs/README.md
@@ -1,4 +1,4 @@
# AWS Secrets Manager Credentials Provider Plugin
# AWS Secrets Manager Credentials Provider

[![Build Status](https://ci.jenkins.io/buildStatus/icon?job=Plugins/aws-secrets-manager-credentials-provider-plugin/master)](https://ci.jenkins.io/blue/organizations/jenkins/Plugins%2Faws-secrets-manager-credentials-provider-plugin/activity/)
[![Jenkins Plugin](https://img.shields.io/jenkins/plugin/v/aws-secrets-manager-credentials-provider.svg)](https://plugins.jenkins.io/aws-secrets-manager-credentials-provider)
Expand All @@ -13,6 +13,7 @@ Access credentials from AWS Secrets Manager in your Jenkins jobs.
- Read-only view of Secrets Manager.
- Credential metadata caching (duration: 5 minutes).
- Jenkins [Configuration As Code](https://github.com/jenkinsci/configuration-as-code-plugin) support.
- [Cross-account](http://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html) Secrets Manager support with IAM roles.

Settings:

Expand All @@ -28,9 +29,9 @@ Settings:

Install and configure the plugin.

### AWS IAM
### IAM

Give Jenkins an [IAM policy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/auth-and-access_identity-based-policies.html) with read access to AWS Secrets Manager.
Give Jenkins read access to Secrets Manager with an [IAM policy](iam/index.md).

Required permissions:

Expand All @@ -39,50 +40,149 @@ Required permissions:

Optional permissions:

- `kms:Decrypt` (if you use a customer-managed AWS KMS key to encrypt the secret)
- `kms:Decrypt` (if you use a customer-managed KMS key to encrypt the secret)

### AWS Secrets Manager
**:warning: We strongly recommend that you use an AWS machine authentication method (such as [EC2 Instance Profiles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html) or [EKS Service Roles](https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html)) to authenticate Jenkins with Secrets Manager.**

Upload secrets to AWS Secrets Manager in the format "one secret value = one AWS Secret" (see the [AWS documentation](https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/create-secret.html)).
## Usage

Text:
1. **Upload the secret** to Secrets Manager as shown below (see also the [AWS documentation](https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/create-secret.html)).
2. **Reference the secret** by name in your Jenkins job.

A Secrets Manager secret acts as one of the following Jenkins credential types, depending on the data and metadata that you put in it.

### Secret Text

A simple secret string.

```bash
aws secretsmanager create-secret --name 'newrelic-token' --description 'Acme Corp Newrelic API token' --secret-string 'abc123'
aws secretsmanager create-secret --name 'newrelic-api-key' --secret-string 'abc123' --description 'Acme Corp Newrelic API key'
```

#### Declarative Pipeline

```groovy
pipeline {
environment {
NEWRELIC_API_KEY = credentials('newrelic-api-key')
}
stages {
stage('Foo') {
echo 'Hello world'
}
}
}
```

#### Scripted Pipeline

```groovy
node {
withCredentials([string(credentialsId: 'newrelic-api-key', variable: 'NEWRELIC_API_KEY')]) {
echo 'Hello world'
}
}
```

Username + Password:
### Username with Password

A username and password pair.

```bash
aws secretsmanager create-secret --name 'artifactory-username' --description 'Acme Corp Artifactory username' --secret-string 'joe'
aws secretsmanager create-secret --name 'artifactory-password' --description 'Acme Corp Artifactory password' --secret-string 'supersecret'
aws secretsmanager create-secret --name 'artifactory' --secret-string 'supersecret' --tags 'Key=jenkins:credentials:username,Value=joe' --description 'Acme Corp Artifactory login'
```

#### Declarative Pipeline

```groovy
pipeline {
environment {
// Creates variables ARTIFACTORY=joe:supersecret, ARTIFACTORY_USR=joe, ARTIFACTORY_PSW=supersecret
ARTIFACTORY = credentials('artifactory')
}
stages {
stage('Foo') {
echo 'Hello world'
}
}
}
```

#### Scripted Pipeline

```groovy
node {
withCredentials([usernamePassword(credentialsId: 'artifactory', usernameVariable: 'ARTIFACTORY_USR', passwordVariable: 'ARTIFACTORY_PSW')]) {
echo 'Hello world'
}
}
```

SSH key:
### SSH User Private Key

A private key with a username.

The plugin supports the following private key formats and encoding schemes:

- **Format**
- PEM
- **Encoding**
- PKCS#1 (starts with `-----BEGIN [ALGORITHM] PRIVATE KEY-----`)
- PKCS#8 (starts with `-----BEGIN PRIVATE KEY-----`)
- OpenSSH (starts with `-----BEGIN OPENSSH PRIVATE KEY-----`)

```bash
ssh-keygen -t rsa -b 4096 -C 'acme@example.com' -f id_rsa
aws secretsmanager create-secret --name 'ssh-key' --description 'Acme Corp SSH key' --secret-string 'file://id_rsa'
aws secretsmanager create-secret --name 'ssh-key' --secret-string 'file://id_rsa' --tags 'Key=jenkins:credentials:username,Value=joe' --description 'Acme Corp SSH key'
```

## Usage

Reference a secret in Secrets Manager by its name in a build job:
#### Declarative Pipeline

```groovy
pipeline {
environment {
ARTIFACTORY_USERNAME = credentials("artifactory-username")
ARTIFACTORY_PASSWORD = credentials("artifactory-password")
// Creates variables KEY=/temp/path/to/key, KEY_USR=joe
KEY = credentials('ssh-key')
}
stages {
stage("Deploy") {
sh "mvn deploy"
stage('Foo') {
echo 'Hello world'
}
}
}
```

#### Scripted Pipeline

```groovy
node {
withCredentials([sshUserPrivateKey(credentialsId: 'ssh-key', keyFileVariable: 'KEY', usernameVariable: 'KEY_USR')]) {
echo 'Hello world'
}
}
```

### Certificate

A client certificate in PKCS#12 format.

The plugin requires the .p12 file to be encrypted with a zero-length password, as demonstrated below.

```bash
openssl pkcs12 -export -in /path/to/cert.pem -inkey /path/to/key.pem -out certificate.p12 -passout pass:
aws secretsmanager create-secret --name 'code-signing-cert' --secret-binary 'fileb://certificate.p12' --description 'Acme Corp code signing certificate'
```

#### Scripted Pipeline

```groovy
node {
withCredentials([certificate(credentialsId: 'code-signing-cert', keystoreVariable: 'STORE_FILE')]) {
echo 'Hello world'
}
}
```

## Configuration

The plugin's default behavior requires **no configuration**.
Expand Down Expand Up @@ -111,8 +211,7 @@ unclassified:

## Bugs

- All secrets must be uploaded via the AWS CLI or API. This is because the AWS Web console *currently* insists on wrapping your secret string in JSON.
- All secrets must be in "secret string" format (not "secret binary") as Jenkins will parse them into (UTF-8) string credentials. You can base64 encode a binary secret to work around this.
All secrets must be uploaded via the AWS CLI or API. This is because the AWS Web console *currently* insists on wrapping your secret string in JSON.

## Development

Expand Down
48 changes: 0 additions & 48 deletions docs/examples/iam.md

This file was deleted.

14 changes: 14 additions & 0 deletions docs/iam/all.json
@@ -0,0 +1,14 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "secretsmanager:ListSecrets"
}
]
}
9 changes: 9 additions & 0 deletions docs/iam/index.md
@@ -0,0 +1,9 @@
# [AWS Secrets Manager Credentials Provider](../README.md)

## IAM Policies

Examples of AWS Secrets Manager [IAM policies](https://docs.aws.amazon.com/secretsmanager/latest/userguide/auth-and-access_identity-based-policies.html) to use with this Jenkins plugin.

- [all.json](all.json) (Allow access to all AWS secrets)
- [secret-id.json](secret-id.json) (Filter by AWS secret ID)
- [secret-namespace-id.json](secret-namespace-id.json) (Filter by AWS secret namespace ID)
14 changes: 14 additions & 0 deletions docs/iam/secret-id.json
@@ -0,0 +1,14 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>"
},
{
"Effect": "Allow",
"Action": "secretsmanager:ListSecrets"
}
]
}
14 changes: 14 additions & 0 deletions docs/iam/secret-namespace-id.json
@@ -0,0 +1,14 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<namespace>/*"
},
{
"Effect": "Allow",
"Action": "secretsmanager:ListSecrets"
}
]
}
Binary file added docs/img/install.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.