Skip to content
This repository has been archived by the owner on Aug 7, 2024. It is now read-only.

Commit

Permalink
feat: Add Rolebinding check support + change secret name format (#37)
Browse files Browse the repository at this point in the history
* feat: update README + Changelog

* feat(breaking): Add support for rolebinding checks

* fix: bump go version
  • Loading branch information
RileyWilliams authored Mar 16, 2022
1 parent ae0cbd1 commit 98cc2de
Show file tree
Hide file tree
Showing 20 changed files with 664 additions and 106 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.14
go-version: 1.16

- name: Checkout code
uses: actions/checkout@v2
Expand Down Expand Up @@ -121,7 +121,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.14
go-version: 1.16

- name: Checkout code
uses: actions/checkout@v2
Expand Down Expand Up @@ -163,7 +163,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.14
go-version: 1.16

- name: Checkout code
uses: actions/checkout@v2
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.14
go-version: 1.16
- name: Checkout code
uses: actions/checkout@v2
- name: Lint code
Expand All @@ -28,7 +28,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.14
go-version: 1.16
- name: Checkout code
uses: actions/checkout@v2
- uses: actions/cache@v2
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ vendor/

# Ignore test keys
*.pem

codeql
codeql-go/
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# v0.1.0

## Breaking Changes
- Support for rolebindings
- Change secret format to use `-` instead of `_`
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ Since we were already using OIDC tokens for user auth/z to the cluster with `kub

Our service creates AWS Secrets Manager secrets with the following naming convention:

**Breaking Change**
*As of version 0.1.0, the secret naming convention has been updated*
```
k8s-secret_secret-namespace_secret-name
k8s-secret-secret-namespace-secret-name
```

We then have `external-secrets` annotations on our namespaces to only allow `ExternalSecret` resources in that namespace to sync with AWS Secrets Manager secrets logically scoped to the namespace. For example, this shows a namespace called `security` that is only allowed to read AWS Secrets Manager secrets prefixed by `k8s-secret_security_`:
Expand All @@ -35,7 +37,7 @@ kind: Namespace
metadata:
name: security
annotations:
externalsecrets.kubernetes-client.io/permitted-key-name: "k8s-secret_security_.*"
externalsecrets.kubernetes-client.io/permitted-key-name: "k8s-secret_security-.*"
```
A member of the `security` namespace can then create a secret with `kiss` and use it as such:
Expand Down
69 changes: 35 additions & 34 deletions client/cmd/main.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
package main

import (
"encoding/json"
"bufio"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"path"
"sort"
"strings"
"time"

"github.com/hashicorp/logutils"
"github.com/ovotech/kiss/client"

pb "github.com/ovotech/kiss/proto"
)

Expand Down Expand Up @@ -107,8 +109,7 @@ func main() {
// We initialize logging here because we need -debug from flags
initLogging()
validateCommonParams()

token, err := loadToken(&tokenPath)
token, err := client.LoadToken(&tokenPath)
if err != nil {
log.Fatalf("[ERROR] Failed to load token from %s", tokenPath)
}
Expand All @@ -127,8 +128,21 @@ func main() {
case "ping":
client.Ping(kissClient, timeout, namespace)
case "create":
if *createSecretName == "" || *createSecretValue == "" {
log.Fatalf("[ERROR] -name and -value are required, see help for more details.")
if *createSecretName == "" {
log.Fatalf("[ERROR] -name is required, see help for more details.")
}
if *createSecretValue == "" {

reader := bufio.NewReader(os.Stdin)
var err error
fmt.Print("Enter secret value:")
input, err := reader.ReadString('\n')
if err != nil {
log.Fatalln("[ERROR] failed to read input from stdin. Either -value is required or you provided an invalid input")
}

*createSecretValue = strings.TrimSpace(input) // otherwise, we would have a blank line

}
client.CreateSecret(kissClient, timeout, namespace, *createSecretName, *createSecretValue)
if *createSecretPolicy {
Expand All @@ -138,7 +152,7 @@ func main() {
client.ListSecrets(kissClient, timeout, namespace)
case "bind":
if *bindSecretName == "" || *bindSecretServiceAccount == "" {
log.Fatalf("[ERROR] -name and -service-acount are required, see help for more details")
log.Fatalf("[ERROR] -name and -service-account are required, see help for more details")
}
client.BindSecret(
kissClient,
Expand All @@ -148,10 +162,23 @@ func main() {
*bindSecretServiceAccount,
)
case "update":
if *updateSecretName == "" || *updateSecretValue == "" {
if *updateSecretName == "" {
log.Fatalf("[ERROR] -name and -value are required, see help for more details.")
}
if *updateSecretValue == "" {

reader := bufio.NewReader(os.Stdin)
var err error
fmt.Print("Enter secret value:")
input, err := reader.ReadString('\n')
if err != nil {
log.Fatalln("[ERROR] failed to read input from stdin. Either -value is required or you provided an invalid input")
}
*updateSecretValue = strings.TrimSpace(input) // otherwise, we would have a blank line
}

client.UpdateSecret(kissClient, timeout, namespace, *updateSecretName, *updateSecretValue)

case "delete":
if *deleteSecretName == "" {
log.Fatalf("[ERROR] -name is required, see help for more details.")
Expand Down Expand Up @@ -191,7 +218,7 @@ func setupCommonFlags() {
"The kiss server address in the format of host:port",
)
fs.DurationVar(
&timeout, "timeout", 30*time.Second, "The interval before a connection times out",
&timeout, "timeout", 10*time.Second, "The interval before a connection times out",
)
fs.StringVar(
&tokenPath,
Expand Down Expand Up @@ -241,29 +268,3 @@ func guessTokenPath() (string, error) {

return tokenPath, nil
}

func loadToken(tokenPath *string) (*string, error) {
jsonFile, err := os.Open(*tokenPath)
if err != nil {
return nil, err
}
defer jsonFile.Close()

bytes, err := ioutil.ReadAll(jsonFile)
if err != nil {
return nil, err
}

var tokenMap map[string]string
err = json.Unmarshal([]byte(bytes), &tokenMap)
if err != nil {
return nil, err
}

idToken, ok := tokenMap["id_token"]
if !ok {
return nil, fmt.Errorf("no 'id_token' field in token file")
}

return &idToken, nil
}
10 changes: 8 additions & 2 deletions client/conn.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package client

import (
"context"
"crypto/tls"
"flag"
"log"
"strconv"
"time"

"google.golang.org/grpc"
Expand Down Expand Up @@ -36,11 +38,15 @@ func GetConnection(
opts = append(opts,
grpc.WithBlock(),
grpc.WithUnaryInterceptor(authInterceptor.Unary()),
grpc.FailOnNonTempDialError(true),
)

// Establish gRPC connection
log.Print("[DEBUG] Creating gRPC Dial...")
conn, err := grpc.Dial(serverAddr, opts...)
log.Printf("[DEBUG] Creating gRPC Dial... (%s) secure=%s", serverAddr, strconv.FormatBool(secure))
// conn, err := grpc.Dial(serverAddr, opts...)
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
conn, err := grpc.DialContext(ctx, serverAddr, opts...)

return conn, err
}
4 changes: 3 additions & 1 deletion client/list_secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
pb "github.com/ovotech/kiss/proto"
)

func ListSecrets(client pb.KISSClient, timeout time.Duration, namespace string) {
func ListSecrets(client pb.KISSClient, timeout time.Duration, namespace string) []string {
log.Println("[DEBUG] Listing secrets...")
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
Expand All @@ -26,4 +26,6 @@ func ListSecrets(client pb.KISSClient, timeout time.Duration, namespace string)
fmt.Println(secret)
}
}

return response.Secrets
}
34 changes: 34 additions & 0 deletions client/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package client

import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)

func LoadToken(tokenPath *string) (*string, error) {
jsonFile, err := os.Open(*tokenPath)
if err != nil {
return nil, err
}
defer jsonFile.Close()

bytes, err := ioutil.ReadAll(jsonFile)
if err != nil {
return nil, err
}

var tokenMap map[string]string
err = json.Unmarshal([]byte(bytes), &tokenMap)
if err != nil {
return nil, err
}

idToken, ok := tokenMap["id_token"]
if !ok {
return nil, fmt.Errorf("no 'id_token' field in token file")
}

return &idToken, nil
}
9 changes: 6 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/ovotech/kiss

go 1.14
go 1.16

require (
github.com/aws/aws-sdk-go-v2 v1.6.0
Expand All @@ -10,9 +10,12 @@ require (
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.3.1
github.com/aws/aws-sdk-go-v2/service/sts v1.4.1
github.com/aws/smithy-go v1.4.0
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/golang/protobuf v1.4.2
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/golang/protobuf v1.5.2
github.com/hashicorp/logutils v1.0.0
github.com/rs/zerolog v1.22.0
google.golang.org/grpc v1.38.0
k8s.io/api v0.22.4
k8s.io/apimachinery v0.22.4
k8s.io/client-go v0.22.4
)
Loading

0 comments on commit 98cc2de

Please sign in to comment.