Skip to content

Commit c603b6e

Browse files
committed
finshed implementation of plugin
1 parent 4c044d2 commit c603b6e

File tree

11 files changed

+465
-0
lines changed

11 files changed

+465
-0
lines changed

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,15 @@
2121

2222
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
2323
hs_err_pid*
24+
25+
26+
.idea
27+
*.iml
28+
target
29+
work
30+
target
31+
.vscode
32+
.settings
33+
.project
34+
.classpath
35+
.factorypath

Jenkinsfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
buildPlugin(failFast:false, findbugs: [archive: true])

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Introduction
2+
3+
This plugin provides an extension for the [kubernetes-credentials-provider-plugin](https://github.com/jenkinsci/kubernetes-credentials-provider-plugin)
4+
plugin, and the [atlassian-bitbucket-server-integration-plugin](https://github.com/jenkinsci/atlassian-bitbucket-server-integration-plugin) that extend the kubernetes credentials provider to create the special credential type required by the atlassian-bitbucket-server-integration when interacting with a bitbucket server instance.
5+
6+
## Usage
7+
8+
This plugin consumes extends the kubernetes-credentials-provider-plugin to consume kubernetes secrets with a `"jenkins.io/credentials-type"` of `"bitbucketToken"`. These secrets need to have a data property `"text"` that contains a base64 encoded `bearer token` for bitbucket server.
9+
10+
### Example
11+
12+
```
13+
apiVersion: v1
14+
data:
15+
text: c3VwZXJkdXBlcnNlY3JldA==
16+
kind: Secret
17+
metadata:
18+
annotations:
19+
jenkins.io/credentials-description: The Bitbucket token for creating web hooks
20+
labels:
21+
jenkins.io/credentials-type: bitbucketToken
22+
name: bitbucket-hook-token
23+
namespace: jenkins-demo
24+
type: Opaque
25+
```

pom.xml

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<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">
3+
<modelVersion>4.0.0</modelVersion>
4+
<parent>
5+
<groupId>org.jenkins-ci.plugins</groupId>
6+
<artifactId>plugin</artifactId>
7+
<version>3.37</version>
8+
<relativePath />
9+
</parent>
10+
11+
<groupId>io.jenkins.plugins</groupId>
12+
<artifactId>bitbucket-kubernetes-credentials</artifactId>
13+
<version>0.0.1-SNAPSHOT</version>
14+
<packaging>hpi</packaging>
15+
16+
<developers>
17+
<developer>
18+
<id>johnrowl</id>
19+
<name>John Rowley</name>
20+
</developer>
21+
</developers>
22+
23+
<scm>
24+
<connection>scm:git:git://github.com/jenkinsci/${project.artifactId}-plugin.git</connection>
25+
<developerConnection>scm:git:[email protected]:jenkinsci/${project.artifactId}-plugin.git</developerConnection>
26+
<url>https://github.com/jenkinsci/${project.artifactId}-plugin</url>
27+
<tag>${scmTag}</tag>
28+
</scm>
29+
30+
<properties>
31+
<jenkins.version>2.222.3</jenkins.version>
32+
<java.level>8</java.level>
33+
</properties>
34+
<name>Bitbucket Credentials - Kubernetes Intergration</name>
35+
<description>Integrates bitbucket credentials with the k8s credential provider</description>
36+
<licenses>
37+
<license>
38+
<name>MIT License</name>
39+
<url>https://opensource.org/licenses/MIT</url>
40+
</license>
41+
</licenses>
42+
<dependencies>
43+
<dependency>
44+
<groupId>com.cloudbees.jenkins.plugins</groupId>
45+
<artifactId>kubernetes-credentials-provider</artifactId>
46+
<version>0.14</version>
47+
</dependency>
48+
<dependency>
49+
<groupId>io.jenkins.plugins</groupId>
50+
<artifactId>atlassian-bitbucket-server-integration</artifactId>
51+
<version>1.1.0</version>
52+
</dependency>
53+
<dependency>
54+
<groupId>org.jenkins-ci.plugins</groupId>
55+
<artifactId>ssh-credentials</artifactId>
56+
<version>1.14</version>
57+
</dependency>
58+
<!-- logging -->
59+
<dependency>
60+
<groupId>org.slf4j</groupId>
61+
<artifactId>slf4j-api</artifactId>
62+
<version>1.7.26</version>
63+
</dependency>
64+
<dependency>
65+
<groupId>org.slf4j</groupId>
66+
<artifactId>jcl-over-slf4j</artifactId>
67+
<version>1.7.26</version>
68+
</dependency>
69+
<dependency>
70+
<groupId>org.slf4j</groupId>
71+
<artifactId>slf4j-jdk14</artifactId>
72+
<version>1.7.26</version>
73+
</dependency>
74+
<dependency>
75+
<groupId>org.slf4j</groupId>
76+
<artifactId>log4j-over-slf4j</artifactId>
77+
<version>1.7.26</version>
78+
</dependency>
79+
80+
81+
<!-- https://mvnrepository.com/artifact/org.jenkins-ci.plugins/credentials -->
82+
<dependency>
83+
<groupId>org.jenkins-ci.plugins</groupId>
84+
<artifactId>credentials</artifactId>
85+
<version>2.3.1</version>
86+
</dependency>
87+
88+
<dependency>
89+
<groupId>org.mockito</groupId>
90+
<artifactId>mockito-core</artifactId>
91+
<version>3.3.3</version>
92+
<scope>test</scope>
93+
</dependency>
94+
<dependency>
95+
<groupId>org.powermock</groupId>
96+
<artifactId>powermock-core</artifactId>
97+
<version>2.0.7</version>
98+
<scope>test</scope>
99+
</dependency>
100+
<dependency>
101+
<groupId>org.powermock</groupId>
102+
<artifactId>powermock-api-mockito2</artifactId>
103+
<version>2.0.7</version>
104+
<scope>test</scope>
105+
</dependency>
106+
<dependency>
107+
<groupId>org.powermock</groupId>
108+
<artifactId>powermock-module-junit4</artifactId>
109+
<version>2.0.7</version>
110+
<scope>test</scope>
111+
</dependency>
112+
</dependencies>
113+
<repositories>
114+
<repository>
115+
<id>repo.jenkins-ci.org</id>
116+
<url>https://repo.jenkins-ci.org/public/</url>
117+
</repository>
118+
</repositories>
119+
<pluginRepositories>
120+
<pluginRepository>
121+
<id>repo.jenkins-ci.org</id>
122+
<url>https://repo.jenkins-ci.org/public/</url>
123+
</pluginRepository>
124+
</pluginRepositories>
125+
</project>
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright 2020 John Rowley
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
package co.johnrowley.jenkins.bitbucketcredentialsk8s;
25+
26+
import com.cloudbees.jenkins.plugins.kubernetes_credentials_provider.CredentialsConvertionException;
27+
import com.cloudbees.jenkins.plugins.kubernetes_credentials_provider.SecretToCredentialConverter;
28+
import com.cloudbees.jenkins.plugins.kubernetes_credentials_provider.SecretUtils;
29+
import edu.umd.cs.findbugs.annotations.CheckForNull;
30+
import com.atlassian.bitbucket.jenkins.internal.config.BitbucketTokenCredentialsImpl;
31+
import hudson.Extension;
32+
import io.fabric8.kubernetes.api.model.Secret;
33+
import java.util.Base64;
34+
import java.util.logging.Level;
35+
import java.util.logging.Logger;
36+
import java.nio.ByteBuffer;
37+
import java.nio.CharBuffer;
38+
import java.nio.charset.CharacterCodingException;
39+
import java.nio.charset.CharsetDecoder;
40+
import java.nio.charset.CodingErrorAction;
41+
import java.nio.charset.StandardCharsets;
42+
43+
/**
44+
* SecretToCredentialConverter that converts {@link BitbucketTokenCredentialsImpl }.
45+
*/
46+
@Extension
47+
public class BitbucketCredentialConverter extends SecretToCredentialConverter {
48+
private static final Logger LOG = Logger.getLogger(BitbucketCredentialConverter.class.getName());
49+
50+
@Override
51+
public boolean canConvert(String type) {
52+
return "bitbucketToken".equals(type);
53+
}
54+
55+
@Override
56+
public BitbucketTokenCredentialsImpl convert(Secret secret) throws CredentialsConvertionException {
57+
String bearerTokenBase64 = SecretUtils.getNonNullSecretData(secret, "text", "bitbucketToken credential is missing the token (in the text property)");
58+
String bearerToken = SecretUtils.requireNonNull(base64DecodeToString(bearerTokenBase64), "bitbucketToken credential has an invalid token (the data in the text property must be base64 encoded UTF-8)");
59+
60+
return new BitbucketTokenCredentialsImpl(
61+
SecretUtils.getCredentialId(secret),
62+
SecretUtils.getCredentialDescription(secret),
63+
hudson.util.Secret.fromString(bearerToken));
64+
}
65+
66+
/**
67+
* Convert a String representation of the base64 encoded bytes back to a byte[].
68+
* @param s the base64 encoded representation of the bytes.
69+
* @return the byte[] or {@code null} if the string could not be converted.
70+
*/
71+
@CheckForNull // TODO: use the one from SecretUtils when allowed
72+
private static byte[] base64Decode(String s) {
73+
try {
74+
return Base64.getDecoder().decode(s);
75+
} catch (IllegalArgumentException ex) {
76+
LOG.log(Level.WARNING, "failed to base64decode Secret, is the format valid? {0}", ex.getMessage());
77+
}
78+
return null;
79+
}
80+
81+
/**
82+
* Convert a String representation of the base64 encoded bytes of a UTF-8 String back to a String.
83+
* @param s the base64 encoded String representation of the bytes.
84+
* @return the String or {@code null} if the string could not be converted.
85+
*/
86+
@CheckForNull // TODO: use the one from SecretUtils when allowed
87+
public static String base64DecodeToString(String s) {
88+
byte[] bytes = base64Decode(s);
89+
if (bytes != null) {
90+
try {
91+
CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
92+
decoder.onMalformedInput(CodingErrorAction.REPORT);
93+
decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
94+
CharBuffer decode = decoder.decode(ByteBuffer.wrap(bytes));
95+
return decode.toString();
96+
} catch (CharacterCodingException ex) {
97+
LOG.log(Level.WARNING, "failed to covert Secret, is this a valid UTF-8 string? {0}", ex.getMessage());
98+
}
99+
}
100+
return null;
101+
}
102+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright 2020 John Rowley
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
/**
25+
* Contains the bitbucketToken credential provider.
26+
*/
27+
@edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault
28+
@edu.umd.cs.findbugs.annotations.DefaultAnnotation(edu.umd.cs.findbugs.annotations.NonNull.class)
29+
package co.johnrowley.jenkins.bitbucketcredentialsk8s;

src/main/resources/index.jelly

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?jelly escape-by-default='true'?>
2+
<div>
3+
Integrates bitbucketToken credential type from the atlassian-bitbucket-server-integration-plugin with the k8s credential provider.
4+
</div>

0 commit comments

Comments
 (0)