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

Initial development #1

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: maven
directory: /
open-pull-requests-limit: 3
schedule:
interval: daily
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

target
work
7 changes: 7 additions & 0 deletions .mvn/extensions.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.0.0 http://maven.apache.org/xsd/core-extensions-1.0.0.xsd">
<extension>
<groupId>io.jenkins.tools.incrementals</groupId>
<artifactId>git-changelist-maven-extension</artifactId>
<version>1.4</version>
</extension>
</extensions>
3 changes: 3 additions & 0 deletions .mvn/maven.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-Pconsume-incrementals
-Pmight-produce-incrementals
-Dchangelist.format=%d.v%s
7 changes: 7 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
def recentLTS = "2.361.1"
def configurations = [
[ platform: "linux", jdk: "11", jenkins: null ],
[ platform: "linux", jdk: "11", jenkins: recentLTS, javaLevel: "11" ],
]
buildPlugin(configurations: configurations)

131 changes: 130 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,132 @@
# aws-secrets-manager-credentials-provider-folders-plugin

Folders support for the Jenkins [AWS Secrets Manager Credentials Provider](https://github.com/jenkinsci/aws-secrets-manager-credentials-provider-plugin) plugin
[![Build Status](https://ci.jenkins.io/buildStatus/icon?job=Plugins/aws-secrets-manager-credentials-provider-folders-plugin/main)](https://ci.jenkins.io/blue/organizations/jenkins/Plugins%2Faws-secrets-manager-credentials-provider-folders-plugin/activity/)
[![Jenkins Plugin](https://img.shields.io/jenkins/plugin/v/aws-secrets-manager-credentials-provider-folders.svg)](https://plugins.jenkins.io/aws-secrets-manager-credentials-provider-folders)

Folders support for the [AWS Secrets Manager Credentials Provider](https://github.com/jenkinsci/aws-secrets-manager-credentials-provider-plugin) plugin.

:warning: This plugin is **experimental**. It should not be used in a production environment. If you want to try it, you will need to build it from source.

## Overview

This plugin extends the AWS Secrets Manager Credentials Provider plugin to provide folder-scoped credentials. These are credentials which are only visible to jobs in a particular folder (and its subfolders).

This is primarily helpful in the following use cases:

- **Multi-tenancy.** In this use case, you have multiple products (or product teams) on a shared Jenkins. Each product is assigned its own folder on Jenkins. This plugin allows product-scoped credentials, which are only visible to jobs in the product team's folder.
- **Multi-environment.** In this use case, you have one Jenkins server that orchestrates jobs for multiple environments (e.g. staging, production). Each environment is assigned its own folder on Jenkins. This plugin allows environment-scoped credentials, so for example the staging credentials are only visible to jobs in the staging folder, and likewise for production.

In these use cases, the fundamental unit of organization is normally the AWS account. (E.g. each product has its own AWS account, with its own secrets in Secrets Manager.) In each Jenkins folder, you will likely want to configure the credentials provider to assume a role in the corresponding AWS account.

## Setup

1. Build the plugin from source (see the [Development](#Development) instructions below).
2. Install the built plugin `.hpi` on Jenkins.
3. Configure IAM.
4. Configure the plugin on the relevant Jenkins folders (see the [Configuration](#Configuration) instructions below).

Setup is very similar to the AWS Secrets Manager Credentials Provider plugin. The main differences are:

- This plugin is folder-scoped, so you will need to configure it on each folder where you want to have folder-scoped credentials.
- If you use this plugin to connect to Secrets Manager in multiple AWS accounts, you will need to do the IAM configuration in each of the remote AWS accounts.

## Usage

The plugin allows secrets from Secrets Manager to be used as Jenkins credentials. It behaves the same as the upstream AWS Secrets Manager Credentials Provider plugin, except that credentials are scoped to folders (i.e. they are only available to jobs in their respective folder).

Please see the AWS Secrets Manager Credentials Provider plugin README for usage instructions.

## Configuration

The plugin has the same configuration options as the AWS Secrets Manager Credentials Provider plugin. The only difference is that the configuration is set at the folder level, not at the global level.

### Web UI

You can set plugin configuration at the folder level using the Web UI.

Go to `Jenkins` > `<folder>` > `Configure` > `AWS Secrets Manager Credentials Provider`, tick the box to enable it for `<folder>`, and change the settings.

### Configuration As Code (CasC)

You can set plugin configuration at the folder level using Jenkins [Configuration As Code](https://github.com/jenkinsci/configuration-as-code-plugin).

To use CasC with folders, you MUST also have the Job DSL Plugin installed.

Example:

```yaml
jobs:
- script: >
folder('<folder>') {
description('This folder is configured as code')
configure {
it / 'properties' / 'io.jenkins.plugins.credentials.secretsmanager.folders.config.FolderPluginConfiguration' / 'pluginConfiguration' / 'client' / 'endpointConfiguration' / serviceEndpoint << 'https://example.com'
it / 'properties' / 'io.jenkins.plugins.credentials.secretsmanager.folders.config.FolderPluginConfiguration' / 'pluginConfiguration' / 'client' / 'endpointConfiguration' / signingRegion << 'us-east-1'
}
}
```

## Versioning

This plugin is currently **experimental**, so it does not have any stable releases. When it does, a versioning policy will be added here.

## Development

### Git

Start by cloning the project.

**Note for Windows users:** some file paths in this project may exceed the legacy Win32 path length limit. This may cause an error when cloning the project on Windows. If you see this error, enable Git's Windows longpaths support with `git config --system core.longpaths true` (you might need to run Git as Administrator for this to work). Then try to clone the project again.

### Dependencies

- Docker
- Java
- Maven

### Build

In Maven:

```shell script
mvn clean verify
```

In your IDE:

1. Generate translations: `mvn localizer:generate`. (This is a one-off task. You only need to re-run this if you change the translations, or if you clean the Maven `target` directory. If the IDE still cannot find the translation symbols after running `mvn localizer:generate`, use a one-off `mvn compile` instead.)
2. Compile.
3. Run tests.

### Run

You can explore how the plugin works by running it locally with [Moto](https://github.com/getmoto/moto) (the AWS mock)...

Start Moto:

```shell
docker run -it -p 5000:5000 motoserver/moto:3.1.18
```

Upload some fake secrets to Moto (like these):

```shell
aws --endpoint-url http://localhost:5000 secretsmanager create-secret --name 'example-api-key' --secret-string '123456' --tags 'Key=jenkins:credentials:type,Value=string' --description 'Example API key'
```

Start Jenkins with the plugin:

```shell
mvn hpi:run
```

Create a new folder `<folder>`.

Edit the folder's Secrets Manager configuration (go to `Jenkins` -> `<folder>` -> `Configure`) to use Moto:

1. Tick the box to enable the Secrets Manager folder-scoped provider on `<folder>`
2. Enable the `Endpoint Configuration` option
3. Set `Service Endpoint` to `http://localhost:5000`
4. Set `Signing Region` to `us-east-1`
5. Click `Save`
6. Try loading the folder-scoped credentials that have come from Moto, or using them in Jenkins jobs.
9 changes: 9 additions & 0 deletions checkstyle-suppressions.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Checkstyle//DTD SuppressionFilter Configuration 1.0//EN"
"https://checkstyle.org/dtds/suppressions_1_0.dtd">
<suppressions>
<suppress checks="MissingJavadocType" files="java$" />
<suppress checks="Indentation" files="java$" />
<suppress checks="CustomImportOrder" files="java$" />
</suppressions>
161 changes: 161 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>4.52</version>
<relativePath />
</parent>

<groupId>io.jenkins.plugins</groupId>
<artifactId>aws-secrets-manager-credentials-provider-folders</artifactId>
<version>${revision}.${changelist}</version>
<packaging>hpi</packaging>

<name>AWS Secrets Manager Credentials Provider Folders Plugin</name>
<description>Folders support for the AWS Secrets Manager Credentials Provider plugin</description>
<url>https://github.com/jenkinsci/${project.artifactId}-plugin</url>
<inceptionYear>2023</inceptionYear>

<developers>
<developer>
<id>chriskilding</id>
<name>Chris Kilding</name>
</developer>
</developers>

<licenses>
<license>
<name>MIT License</name>
<url>https://opensource.org/licenses/MIT</url>
</license>
</licenses>

<scm>
<connection>https://github.com/jenkinsci/${project.artifactId}-plugin.git</connection>
<developerConnection>scm:git:git@github.com:jenkinsci/${project.artifactId}-plugin.git</developerConnection>
<url>https://github.com/jenkinsci/${project.artifactId}-plugin/blob/main/docs/README.md</url>
<tag>${scmTag}</tag>
</scm>

<properties>
<revision>1</revision>
<changelist>999999-SNAPSHOT</changelist>
<java.level>11</java.level>
<jenkins.version>2.361.1</jenkins.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.jenkins.tools.bom</groupId>
<artifactId>bom-2.361.x</artifactId>
<version>1678.vc1feb_6a_3c0f1</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>io.jenkins.plugins</groupId>
<artifactId>aws-secrets-manager-credentials-provider</artifactId>
<version>1.202.ve0ec0c17611c</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>cloudbees-folder</artifactId>
</dependency>
<dependency>
<groupId>io.jenkins</groupId>
<artifactId>configuration-as-code</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jenkinsci.plugins</groupId>
<artifactId>pipeline-model-definition</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.jenkins.configuration-as-code</groupId>
<artifactId>test-harness</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.21.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.17.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>job-dsl</artifactId>
<version>1.81</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<!-- Parent POM managed plugins -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<tagNameFormat>@{project.version}</tagNameFormat>
</configuration>
</plugin>
<!-- Our plugins -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<configLocation>google_checks.xml</configLocation>
<sourceDirectories>${project.build.sourceDirectory}</sourceDirectories>
<linkXRef>false</linkXRef>
<suppressionsLocation>${project.basedir}/checkstyle-suppressions.xml</suppressionsLocation>
</configuration>
</plugin>
</plugins>
</build>

<repositories>
<repository>
<id>repo.jenkins-ci.org</id>
<url>https://repo.jenkins-ci.org/public/</url>
</repository>
</repositories>

<pluginRepositories>
<pluginRepository>
<id>repo.jenkins-ci.org</id>
<url>https://repo.jenkins-ci.org/public/</url>
</pluginRepository>
</pluginRepositories>
</project>
Loading