Skip to content

Commit

Permalink
Merge pull request #8 from mcanoy/ocp4-user
Browse files Browse the repository at this point in the history
use groups to identify access
  • Loading branch information
mcanoy authored Oct 7, 2019
2 parents aff25e1 + 1e68f41 commit 43eeb2d
Show file tree
Hide file tree
Showing 18 changed files with 331 additions and 177 deletions.
28 changes: 23 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Description

This plugin enables user authentication and Single Sign-On via OpenShift. It is heavily based on the code by Julien Lancelot. Tested on version 7 of Sonarqube and OCP 3.11. It is intended to run deployed in a pod on OpenShift.
This plugin enables user authentication and Single Sign-On via OpenShift. It is based on the code by Julien Lancelot. Tested on version 7 of Sonarqube and OCP 3.11. It is intended to run deployed in a pod on OpenShift.

This plugin is designed to work out of the box without configuration. During plugin deployment, it looks up oauth information from OpenShift's well-known information and takes advantage of information already on the running pod.

Expand All @@ -16,7 +16,7 @@ During deployment the plugin will:

## Installation

This plugin is not currently hosted anywhere. So build and place this plugin on to the volume where Sonarqube reads plugins at startup. Typically, this might be `/opt/sonarqube/data/plugins`.
This plugin is currently hosted at [rht-labs](https://github.com/rht-labs/sonar-auth-openshift/releases/latest). The latest jar is [here](https://github.com/rht-labs/sonar-auth-openshift/releases/latest/download/sonar-auth-openshift-plugin.jar). You can build it locally and place this plugin on to the volume where Sonarqube reads plugins at startup if modifying it. Typically, this might be `/opt/sonarqube/data/plugins`.

The service account can be used as the oauth client in OpenShift. The service account that runs Sonarqube should have a redirect uri that references the route that Sonarqube is using. You must specify this service account in the DeploymentConfig.

Expand Down Expand Up @@ -45,13 +45,31 @@ You may also enable it in the Administrative console

## Configuration

This plugin will map OpenShift roles to Sonarqube roles. These values are set with the property (shown with the default value if property is not set)
This plugin will map OpenShift groups to Sonarqube roles. These values are set with the property

```
sonar.auth.openshift.sar.groups=admin=sonar-administrators,edit=sonar-users,view=sonar-users
sonar.auth.openshift.sar.groups=ocp-admin=sonar-administrators,ocp-users=sonar-users
```

This shows that Sonarqube will allow OpenShift users who are in the group ocp-admin users to be administrators with the role of sonar-administrators. Ordinary users will be added as sonar-users if they are OpenShift users in the group ocp-users. These OpenShift groups do not exist by default.

The default mapping value is:

```
sonar.auth.openshift.sar.groups=sonar-administrators=sonar-administrators,sonar-users=sonar-users
```
To disable certificate validation (not recommended for production) configure the `ignore.certs` property

```
ignore.certs=true
```

The pod that sonarqube runs in should have a valid certificate to access the OpenShift/Kubernetes API. The Oauth server may have a different certificate. That certificate needs to be loaded into the keystore. To do so, place the certificate on the container's file system (via configmap, dockerfile, etc...). Then configure the sonar property to point the location on the file system

```
oauth.cert=/opt/sonarqube/conf/oauth.crt
```

The default shown will allow admin users of the project the role of sonar-administrators of Sonarqube. Edit and View role users will be added as sonar-users.

You may choose the background color of the log in button with the property

Expand Down
2 changes: 1 addition & 1 deletion example/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ RUN cp -a /opt/sonarqube/data /opt/sonarqube/data-init && \
chown root:root /opt/sonarqube && chmod -R gu+rwX /opt/sonarqube
ADD plugins.sh /opt/sonarqube/bin/plugins.sh
RUN /opt/sonarqube/bin/plugins.sh $sonar_plugins
ADD sonar-auth-openshift-plugin-1.0.0.jar /opt/sonarqube/extensions-init/plugins/sonar-auth-openshift-plugin-1.0.0.jar
ADD sonar-auth-openshift-plugin-1.1.0.jar /opt/sonarqube/extensions-init/plugins/sonar-auth-openshift-plugin-1.1.0.jar
RUN chown root:root /opt/sonarqube -R; \
chmod 6775 /opt/sonarqube -R
USER 1001
23 changes: 15 additions & 8 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Example Build and Deploy


```
This example uses ansible. Windows users use a vm or apply each command manually
```
Expand All @@ -15,25 +14,33 @@ This section contains an example for how this plugin can be used with Sonarqube
mvn clean package && cp target/sonar-auth-openshift-plugin-1.0.0.jar example/
```

2. Create a project in OpenShift

```
oc new-project sonarqube
```
2. Inspect the [all.yml](example/inventory/group_vars/all.yml) file. In the following step it will run the [OpenShift Applier](https://github.com/redhat-cop/openshift-applier) to create resources in OpenShift. Most importantly
1. A project / namespace called `sonarqube` that the other resources will belong too.
2. A deployment config to deploy sonarqube with the plugin.
3. A build config to build the sonarqube-auth-openshift project.
4. A route to navigate to the application.
5. Two groups that will define the users and administrators of Sonarqube.
1. Inspect the group allocation. Add/Remove appropriate users for your scenario. Users are listed in the two yaml files located in the files directory. Group creation and editing usually require elvated privileges. Group names are also defined here. If changed, the sonar.properties must also be changed to match.

3. From the example folder run the prerequisites

```
ansible-galaxy install -r requirements.yml --roles-path=roles
```

4. From the example folder run the ansible playbook which sets up the build and deploy for Sonarqube including a persistent volume and database
1. From the example folder, run the ansible playbook which sets up the build and deploy for Sonarqube including a persistent volume and database.

```
ansible-playbook -i inventory/ apply.yml
```
If the group are already setup and you do not want to add them with this playbook run this command instead

```
ansible-playbook -i inventory/ apply.yml -e exclude_tags=users_and_groups
```


5. From the base folder build the Docker container on OpenShift
1. From the base folder, build the Docker container on OpenShift. This will replace the original build with the build with local files.

```
oc start-build sonarqube --from-dir=. -n sonarqube
Expand Down
9 changes: 9 additions & 0 deletions example/files/project.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: project.openshift.io/v1
kind: Project
metadata:
name: sonarqube
spec:
finalizers:
- kubernetes
status:
phase: Active
9 changes: 9 additions & 0 deletions example/files/sonarqube-admin-group.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
apiVersion: user.openshift.io/v1
kind: Group
metadata:
name: sonarqube_admin
users:
- developer
- admin1
- admin2
9 changes: 9 additions & 0 deletions example/files/sonarqube-user-group.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
apiVersion: user.openshift.io/v1
kind: Group
metadata:
name: sonarqube_user
users:
- developer
- casual_user1
- casual_user2
18 changes: 18 additions & 0 deletions example/inventory/group_vars/all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,24 @@ sonarqube:
POSTGRES_DATABASE_NAME: "sonar"

openshift_cluster_content:
- object: project
content:
- name: sonar project
file: "{{ playbook_dir}}/files/project.yml"
tags:
- project
- object: user-groups
content:
- name: group-admin-members
file: "{{ playbook_dir}}/files/sonarqube-admin-group.yml"
namespace: "{{ ci_cd_namespace }}"
tags:
- users_and_groups
- name: group-view-members
file: "{{ playbook_dir}}/files/sonarqube-user-group.yml"
namespace: "{{ ci_cd_namespace }}"
tags:
- users_and_groups
- object: build
content:
- name: sonarqube
Expand Down
4 changes: 3 additions & 1 deletion example/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
set -x
set -e

rm -rf /opt/sonarqube/data/plugins/sonar-auth-openshift-plugin*.jar

## If the mounted data volume is empty, populate it from the default data
cp -a /opt/sonarqube/data-init/* /opt/sonarqube/data/

Expand All @@ -25,4 +27,4 @@ fi

java -jar lib/sonar-application-$SONAR_VERSION.jar \
-Dsonar.web.javaAdditionalOpts="${SONARQUBE_WEB_JVM_OPTS} -Djava.security.egd=file:/dev/./urandom" \
"$@"
"$@"
32 changes: 18 additions & 14 deletions example/sonar.properties
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
sonar.log.console=true
sonar.jdbc.username=${env:JDBC_USERNAME}
sonar.jdbc.password=${env:JDBC_PASSWORD}
sonar.jdbc.url=${env:JDBC_URL}
sonar.forceAuthentication=${env:FORCE_AUTHENTICATION}
sonar.authenticator.createUsers=${env:SONAR_AUTOCREATE_USERS}
sonar.log.level=${env:SONAR_LOG_LEVEL}
http.proxyHost=${env:PROXY_HOST}
http.proxyPort=${env:PROXY_PORT}
http.proxyUser=${env:PROXY_USER}
http.proxyPassword=${env:PROXY_PASSWORD}
kubernetes.service=https://${env:KUBERNETES_SERVICE_HOST}:${env:KUBERNETES_SERVICE_PORT}/
sonar.auth.openshift.isEnabled=true
sonar.auth.openshift.button.color=#000000
sonar.log.console=true
sonar.jdbc.username=${env:JDBC_USERNAME}
sonar.jdbc.password=${env:JDBC_PASSWORD}
sonar.jdbc.url=${env:JDBC_URL}
sonar.forceAuthentication=${env:FORCE_AUTHENTICATION}
sonar.authenticator.createUsers=${env:SONAR_AUTOCREATE_USERS}
sonar.log.level=${env:SONAR_LOG_LEVEL}
http.proxyHost=${env:PROXY_HOST}
http.proxyPort=${env:PROXY_PORT}
http.proxyUser=${env:PROXY_USER}
http.proxyPassword=${env:PROXY_PASSWORD}
kubernetes.service=https://${env:KUBERNETES_SERVICE_HOST}:${env:KUBERNETES_SERVICE_PORT}/
sonar.auth.openshift.isEnabled=true
sonar.auth.openshift.button.color=#000000
sonar.auth.openshift.sar.groups=sonarqube_admin=sonar-administrators,sonarqube_user=sonar-users
ignore.certs=false
#oauth.cert=/opt/sonarqube/conf/oauth.crt

2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<groupId>org.sonarsource.auth.openshift</groupId>
<artifactId>sonar-auth-openshift-plugin</artifactId>
<packaging>sonar-plugin</packaging>
<version>1.0.0</version>
<version>1.1.0</version>

<name>OpenShift Authentication for SonarQube</name>
<description><![CDATA[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

import java.io.BufferedReader;
import java.io.File;

import java.io.FileInputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
Expand All @@ -28,17 +28,18 @@ public class OpenShiftConfiguration {

private final Configuration config;
private static final String DEFAULT_SCOPE = "user:info user:check-access";
private static final String DEFAULT_GROUPS = "admin=sonar-administrators,edit=sonar-users,view=sonar-users";
private static final String DEFAULT_GROUPS = "sonar-administrators=sonar-administrators,sonar-users=sonar-users";
private static final String DEFAULT_SERVICEACCOUNT_DIRECTORY = "/run/secrets/kubernetes.io/serviceaccount";

private static final String SERVICEACCOUNT_DIRECTORY_KEY = "kubernetes.service.account.dir";

private static final String USER_URI = "oapi/v1/users/~";
private static final String SAR_URI = "oapi/v1/subjectaccessreviews";
private static final String USER_URI = "apis/user.openshift.io/v1/users/~";
private static final String ROUTE_URI = "%sapis/route.openshift.io/v1/namespaces/%s/routes/%s";
private static final String CATEGORY = "OpenShift-Auth";
private static final String SUBCATEGORY = "Authentication";

private static final String OPENSHIFT_GROUP_MAPPING = "sonar.auth.openshift.sar.groups";
private static final String OAUTH_CERT = "oauth.cert";
private static final String IGNORE_CERTS = "ignore.certs";
private static final String WEB_URL = "sonar.auth.openshift.webUrl";
private static final String API_URL = "kubernetes.service";
private static final String IS_ENABLED = "sonar.auth.openshift.isEnabled";
Expand All @@ -59,11 +60,21 @@ public OpenShiftConfiguration(Configuration config) {
public String getCert() {
return CA_CRT;
}

public String getSarURI() {
return getApiURL() + SAR_URI;
}

public FileInputStream getOAuthCertFile() throws FileNotFoundException {
String cert = config.get(OAUTH_CERT).orElse(null);

if(cert == null) {
return null;
}

return new FileInputStream(new File(cert));
}

public boolean ignoreCerts() {
return config.getBoolean(IGNORE_CERTS).orElse(false);
}

public String getUserURI() {
return getApiURL() + USER_URI;
}
Expand Down Expand Up @@ -97,7 +108,7 @@ public boolean getAllowUsersToSignUp() {
}

public Map<String, String> getSARGroups() {
String mapAsString = config.get("sonar.auth.openshift.sar.groups").orElse(DEFAULT_GROUPS);
String mapAsString = config.get(OPENSHIFT_GROUP_MAPPING).orElse(DEFAULT_GROUPS);
return Splitter.on(",").withKeyValueSeparator("=").split(mapAsString);
}

Expand Down
Loading

0 comments on commit 43eeb2d

Please sign in to comment.