Skip to content

Commit

Permalink
Issue:239 Accept auth secret (#250)
Browse files Browse the repository at this point in the history
* Issue:239 Accept auth secret

Signed-off-by: pbelgundi <[email protected]>

* Added documentation and implemented review comments

Signed-off-by: pbelgundi <[email protected]>

* minor corrections to auth doc

Signed-off-by: pbelgundi <[email protected]>

* added null check for secret name when auth enabled

Signed-off-by: pbelgundi <[email protected]>

* correction

Signed-off-by: pbelgundi <[email protected]>

* changes to auth documentation

Signed-off-by: pbelgundi <[email protected]>

* documentation changes and comments

Signed-off-by: pbelgundi <[email protected]>

* doc changes

Signed-off-by: pbelgundi <[email protected]>
Signed-off-by: pbelgundi <[email protected]>
  • Loading branch information
pbelgundi committed Aug 22, 2019
1 parent aa22eb0 commit 7f9c8e7
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 31 deletions.
78 changes: 78 additions & 0 deletions doc/auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Enable Authentication

Pravega supports pluggable authentication and authorization (referred to as auth for short). For details please see [Pravega Authentication](https://github.com/pravega/pravega/blob/master/documentation/src/docs/auth/auth-plugin.md).

By default, the PasswordAuthHandler plugin is installed on the system.
To use the default `PasswordAuthHandler` plugin for `auth`, the following steps can be followed:

1. Create a file containing `<user>:<password>:<acl>;` with one line per user.
Delimiter should be `:` with `;` at the end of each line.
Use the [PasswordCreatorTool](https://github.com/pravega/pravega/blob/master/controller/src/test/java/io/pravega/controller/auth/PasswordFileCreatorTool.java) to create a new file with the password encrypted.
Use this file when creating the secret in next step.

Sample encrypted password file:
```
$ cat userdata.txt
admin:353030303a633132666135376233353937356534613430383430373939343839333733616463363433616532363238653930346230333035393666643961316264616661393a3639376330623663396634343864643262663335326463653062613965336439613864306264323839633037626166663563613166333733653631383732353134643961303435613237653130353633633031653364366565316434626534656565636335663666306465663064376165313765646263656638373764396361:*,READ_UPDATE;
```

2. Create a kubernetes secret with this file:

```
$ kubectl create secret generic password-auth \
--from-file=./userdata.txt \
```

Ensure secret is created:

```
$ kubectl describe secret password-auth
Name: password-auth
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
userdata.txt: 418 bytes
```

3. Specify the secret names in the `authentication` block and these parameters in the `options` block.

```
apiVersion: "pravega.pravega.io/v1alpha1"
kind: "PravegaCluster"
metadata:
name: "example"
spec:
authentication:
enabled: true
passwordAuthSecret: password-auth
...
pravega:
options:
controller.auth.enabled: "true"
controller.auth.userPasswordFile: "/etc/auth-passwd-volume/userdata.txt"
controller.auth.tokenSigningKey: "secret"
autoScale.authEnabled: "true"
autoScale.tokenSigningKey: "secret"
pravega.client.auth.token: "YWRtaW46MTExMV9hYWFh"
pravega.client.auth.method: "Basic"
...
```

`pravega.client.auth.method` and `pravega.client.auth.token` represent the auth method and token to be used for internal communications from the Segment Store to the Controller.
If you intend to use the default auth plugin, these values are:
```
pravega.client.auth.method: Basic
pravega.client.auth.token: Base64 encoded value of <username>:<pasword>,
```
where username and password are credentials you intend to use.

Note that Pravega operator uses `/etc/auth-passwd-volume` as the mounting directory for secrets.

For more security configurations, please check [here](https://github.com/pravega/pravega/blob/master/documentation/src/docs/security/pravega-security-configurations.md).
1 change: 1 addition & 0 deletions doc/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ This document explains how to configure Pravega
* [Tune Pravega Configuration](pravega-options.md)
* [Tune Bookkeeper Configuration](bookkeeper-options.md)
* [Enable TLS](tls.md)
* [Enable Authentication](auth.md)
* [Enable external access](external-access.md)
* [Enable admission webhook](webhook.md)
28 changes: 27 additions & 1 deletion pkg/apis/pravega/v1alpha1/pravegacluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ type PravegaCluster struct {
// WithDefaults set default values when not defined in the spec.
func (p *PravegaCluster) WithDefaults() (changed bool) {
changed = p.Spec.withDefaults()

return changed
}

Expand All @@ -78,6 +77,11 @@ type ClusterSpec struct {
// https://github.com/pravega/pravega/blob/master/documentation/src/docs/security/pravega-security-configurations.md
TLS *TLSPolicy `json:"tls,omitempty"`

// Authentication can be enabled for authorizing all communication from clients to controller and segment store
// See the following file for a complete list of options:
// https://github.com/pravega/pravega/blob/master/documentation/src/docs/security/pravega-security-configurations.md
Authentication *AuthenticationParameters `json:"authentication,omitempty"`

// Version is the expected version of the Pravega cluster.
// The pravega-operator will eventually make the Pravega cluster version
// equal to the expected version.
Expand Down Expand Up @@ -117,6 +121,11 @@ func (s *ClusterSpec) withDefaults() (changed bool) {
}
}

if s.Authentication == nil {
changed = true
s.Authentication = &AuthenticationParameters{}
}

if s.Version == "" {
s.Version = DefaultPravegaVersion
changed = true
Expand Down Expand Up @@ -196,6 +205,23 @@ func (tp *TLSPolicy) IsSecureSegmentStore() bool {
return len(tp.Static.SegmentStoreSecret) != 0
}

type AuthenticationParameters struct {
// Enabled specifies whether or not authentication is enabled
// By default, authentication is not enabled
Enabled bool `json:"enabled"`

// name of Secret containing Password based Authentication Parameters like username, password and acl
// optional - used only by PasswordAuthHandler for authentication
PasswordAuthSecret string `json:"passwordAuthSecret,omitempty"`
}

func (ap *AuthenticationParameters) IsEnabled() bool {
if ap == nil {
return false
}
return ap.Enabled
}

// ImageSpec defines the fields needed for a Docker repository image
type ImageSpec struct {
Repository string `json:"repository"`
Expand Down
21 changes: 12 additions & 9 deletions pkg/controller/pravega/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@
package pravega

const (
cacheVolumeName = "cache"
cacheVolumeMountPoint = "/tmp/pravega/cache"
tier2FileMountPoint = "/mnt/tier2"
tier2VolumeName = "tier2"
segmentStoreKind = "pravega-segmentstore"
tlsVolumeName = "tls-secret"
tlsMountDir = "/etc/secret-volume"
heapDumpName = "heap-dump"
heapDumpDir = "/tmp/dumpfile/heap"
cacheVolumeName = "cache"
cacheVolumeMountPoint = "/tmp/pravega/cache"
tier2FileMountPoint = "/mnt/tier2"
tier2VolumeName = "tier2"
segmentStoreKind = "pravega-segmentstore"
tlsVolumeName = "tls-secret"
tlsMountDir = "/etc/secret-volume"
heapDumpName = "heap-dump"
heapDumpDir = "/tmp/dumpfile/heap"
authVolumeName = "auth-passwd-secret"
authMountDir = "/etc/auth-passwd-volume"
defaultTokenSigningKey = "secret"
)
51 changes: 31 additions & 20 deletions pkg/controller/pravega/pravega_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
package pravega

import (
"strings"

"fmt"
"strings"

api "github.com/pravega/pravega-operator/pkg/apis/pravega/v1alpha1"
"github.com/pravega/pravega-operator/pkg/util"
Expand Down Expand Up @@ -133,29 +132,42 @@ func makeControllerPodSpec(p *api.PravegaCluster) *corev1.PodSpec {
}

configureControllerTLSSecrets(podSpec, p)

configureAuthSecrets(podSpec, p)
return podSpec
}

func configureControllerTLSSecrets(podSpec *corev1.PodSpec, p *api.PravegaCluster) {
if p.Spec.TLS.IsSecureController() {
vol := corev1.Volume{
Name: tlsVolumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: p.Spec.TLS.Static.ControllerSecret,
},
},
}
podSpec.Volumes = append(podSpec.Volumes, vol)
addSecretVolumeWithMount(podSpec, p, tlsVolumeName, p.Spec.TLS.Static.ControllerSecret, tlsVolumeName, tlsMountDir)
}
}

podSpec.Containers[0].VolumeMounts = append(podSpec.Containers[0].VolumeMounts, corev1.VolumeMount{
Name: tlsVolumeName,
MountPath: tlsMountDir,
})
func configureAuthSecrets(podSpec *corev1.PodSpec, p *api.PravegaCluster) {
if p.Spec.Authentication.IsEnabled() && p.Spec.Authentication.PasswordAuthSecret != "" {
addSecretVolumeWithMount(podSpec, p, authVolumeName, p.Spec.Authentication.PasswordAuthSecret,
authVolumeName, authMountDir)
}
}

func addSecretVolumeWithMount(podSpec *corev1.PodSpec, p *api.PravegaCluster,
volumeName string, secretName string,
mountName string, mountDir string) {
vol := corev1.Volume{
Name: volumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: secretName,
},
},
}
podSpec.Volumes = append(podSpec.Volumes, vol)

podSpec.Containers[0].VolumeMounts = append(podSpec.Containers[0].VolumeMounts, corev1.VolumeMount{
Name: mountName,
MountPath: mountDir,
})
}

func MakeControllerConfigMap(p *api.PravegaCluster) *corev1.ConfigMap {
var javaOpts = []string{
"-Xms512m",
Expand All @@ -179,15 +191,15 @@ func MakeControllerConfigMap(p *api.PravegaCluster) *corev1.ConfigMap {
javaOpts = append(javaOpts, fmt.Sprintf("-D%v=%v", name, value))
}

authEnabledStr := fmt.Sprint(p.Spec.Authentication.IsEnabled())
configData := map[string]string{
"CLUSTER_NAME": p.Name,
"ZK_URL": p.Spec.ZookeeperUri,
"JAVA_OPTS": strings.Join(javaOpts, " "),
"REST_SERVER_PORT": "10080",
"CONTROLLER_SERVER_PORT": "9090",
"AUTHORIZATION_ENABLED": "false",
"TOKEN_SIGNING_KEY": "secret",
"USER_PASSWORD_FILE": "/etc/pravega/conf/passwd",
"AUTHORIZATION_ENABLED": authEnabledStr,
"TOKEN_SIGNING_KEY": defaultTokenSigningKey,
"TLS_ENABLED": "false",
"WAIT_FOR": p.Spec.ZookeeperUri,
}
Expand All @@ -204,7 +216,6 @@ func MakeControllerConfigMap(p *api.PravegaCluster) *corev1.ConfigMap {
},
Data: configData,
}

return configMap
}

Expand Down
3 changes: 2 additions & 1 deletion pkg/controller/pravega/pravega_segmentstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,9 @@ func MakeSegmentstoreConfigMap(p *api.PravegaCluster) *corev1.ConfigMap {
javaOpts = append(javaOpts, fmt.Sprintf("-D%v=%v", name, value))
}

authEnabledStr := fmt.Sprint(p.Spec.Authentication.IsEnabled())
configData := map[string]string{
"AUTHORIZATION_ENABLED": "false",
"AUTHORIZATION_ENABLED": authEnabledStr,
"CLUSTER_NAME": p.Name,
"ZK_URL": p.Spec.ZookeeperUri,
"JAVA_OPTS": strings.Join(javaOpts, " "),
Expand Down

0 comments on commit 7f9c8e7

Please sign in to comment.