diff --git a/.github/workflows/docker-build-publish.yaml b/.github/workflows/docker-build-publish.yaml
index 1bd75dd..37820aa 100644
--- a/.github/workflows/docker-build-publish.yaml
+++ b/.github/workflows/docker-build-publish.yaml
@@ -110,7 +110,19 @@ jobs:
go version
rm -rf example
go test -v -race -covermode=atomic -coverprofile=coverage.out ./...
- go tool cover -html=coverage.out -o coverage.html
+
+ # This action uploads coverage to Codecov.
+ # https://github.com/codecov/codecov-action
+ -
+ name: Upload coverage to Codecov
+ id: go-coverage
+ uses: codecov/codecov-action@v3
+ with:
+ files: ./coverage.out
+ flags: unittests
+ fail_ci_if_error: true
+ verbose: true
+ version: "latest"
# The Github action runs CIS Dockerfile benchmark against dockerfiles in repository (CIS 4.1, 4.2, 4.3, 4.6, 4.7, 4.9, 4.10)
# https://github.com/sysdiglabs/benchmark-dockerfile
diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml
new file mode 100644
index 0000000..9c98c89
--- /dev/null
+++ b/.github/workflows/lint.yaml
@@ -0,0 +1,85 @@
+name: lint
+
+on:
+ # If any commit message in your push or the HEAD commit of your PR contains the strings
+ # [skip ci], [ci skip], [no ci], [skip actions], or [actions skip]
+ # workflows triggered on the push or pull_request events will be skipped.
+ # https://github.blog/changelog/2021-02-08-github-actions-skip-pull-request-and-push-workflows-with-skip-ci/
+ push:
+ branches: [ master ]
+ # Publish semver tags as releases.
+ tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ]
+ # If any commit message in your push or the HEAD commit of your PR contains the strings
+ # [skip ci], [ci skip], [no ci], [skip actions], or [actions skip]
+ # workflows triggered on the push or pull_request events will be skipped.
+ # https://github.blog/changelog/2021-02-08-github-actions-skip-pull-request-and-push-workflows-with-skip-ci/
+ pull_request:
+ branches: [ master ]
+
+env:
+ GOLANG_VERSION: ^1.19
+
+jobs:
+ # This job runs golangci-lint and reports issues from linters.
+ # https://github.com/golangci/golangci-lint-action
+ golangci-lint:
+ name: golangci-lint
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+ - name: Setup Golang
+ uses: actions/setup-go@v3
+ with:
+ go-version: ${{ env.GOLANG_VERSION }}
+ - name: golangci-lint
+ uses: golangci/golangci-lint-action@v3
+ # continue-on-error: true
+ with:
+ # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
+ version: "latest"
+ # Optional: golangci-lint command line arguments.
+ args: --issues-exit-code=0 -c ./.golangci.yml
+
+ # This job runs markdownlint and reports issues from linters.
+ # https://github.com/DavidAnson/markdownlint-cli2-action
+ markdownlint:
+ name: markdownlint
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+ - name: markdownlint
+ uses: DavidAnson/markdownlint-cli2-action@v7
+ continue-on-error: true
+ with:
+ globs: |
+ README.md
+ CHANGELOG.md
+ docs/*.md
+
+ CodeQL:
+ name: CodeQL
+ runs-on: ubuntu-latest
+ permissions:
+ security-events: write
+ actions: read
+ strategy:
+ fail-fast: false
+ matrix:
+ language: ['go']
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ languages: ${{ matrix.language }}
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v2
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
diff --git a/.golangci.yml b/.golangci.yml
index a35765f..66d2a91 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,6 +1,31 @@
linters-settings:
errcheck:
- ignore: fmt:.*,glg:.*
+ ignore: "fmt:.*,github.com/kpango/glg:.*"
issues:
- exclude:
- - Error return value of .(glg.(Info|Log|Debug|Warn|Error|Success|Fail|Print|Println|CustomLog)f?). is not checked
+ max-same-issues: 0
+ # exclude:
+ # - Error return value of .(glg.(Info|Log|Debug|Warn|Error|Success|Fail|Print|Println|CustomLog)f?). is not checked
+linters:
+ presets:
+ # - bugs
+ - comment
+ # - complexity
+ # - error
+ # - format
+ # - import
+ # - metalinter
+ - module
+ - performance
+ # - sql
+ # - style
+ # - test
+ - unused
+ disable:
+ - varcheck
+ - deadcode
+ - structcheck
+ - maligned
+ - dupword
+ - godox
+ - gomoddirectives
+ - godot
diff --git a/.remarkrc b/.remarkrc
deleted file mode 100644
index 674075b..0000000
--- a/.remarkrc
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "plugins": [
- "remark-preset-lint-consistent",
- "remark-preset-lint-recommended",
- ["remark-lint-list-item-indent", false],
- ["remark-lint-list-item-bullet-indent", false],
- ["remark-lint-list-item-content-indent", false]
- ]
-}
diff --git a/Makefile b/Makefile
index d588422..626ce8f 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,10 @@ GO_VERSION:=$(shell go version)
.PHONY: all clean bench bench-all profile lint test contributors update install
-all: clean install lint test bench
+all: build
+
+build:
+ go build
clean:
go clean ./...
@@ -36,7 +39,7 @@ deps: clean
rm -rf vendor
lint:
- gometalinter --enable-all . | rg -v comment
+ golangci-lint run -c ./.golangci.yml
test: clean init
GO111MODULE=on go test --race -v ./...
diff --git a/README.md b/README.md
index 27b8e92..157267b 100644
--- a/README.md
+++ b/README.md
@@ -9,17 +9,18 @@
![logo](./images/logo.png)
-
+
- [What is Garm](#what-is-garm)
- [Use Case](#use-case)
- - [Authorization](#authorization)
- - [Docker](#docker)
- - [Usage](#usage)
+ - [Authorization](#authorization)
+ - [Docker](#docker)
+ - [Usage](#usage)
- [Contributor License Agreement](#contributor-license-agreement)
- [About releases](#about-releases)
+
## What is Garm
@@ -51,8 +52,9 @@ Garm convert the K8s request to Athenz request based on the mapping rules in `co
P.S. It is just a sample deployment solution above. Garm can work on any environment as long as it can access both the API server and the Athenz server.
### Docker
-```shell
-$ docker pull docker.io/athenz/garm
+
+```bash
+docker pull docker.io/athenz/garm
```
### Usage
@@ -70,5 +72,5 @@ Note that only for contributions to the garm repository on the [GitHub](https://
## About releases
- Releases
- - [![GitHub release (latest by date)](https://img.shields.io/github/v/release/AthenZ/garm?style=flat-square&label=Github%20version)](https://github.com/AthenZ/garm/releases/latest)
- - [![Docker Image Version (tag latest)](https://img.shields.io/docker/v/athenz/garm/latest?style=flat-square&label=Docker%20version)](https://hub.docker.com/r/athenz/garm/tags)
+ - [![GitHub release (latest by date)](https://img.shields.io/github/v/release/AthenZ/garm?style=flat-square&label=Github%20version)](https://github.com/AthenZ/garm/releases/latest)
+ - [![Docker Image Version (tag latest)](https://img.shields.io/docker/v/athenz/garm/latest?style=flat-square&label=Docker%20version)](https://hub.docker.com/r/athenz/garm/tags)
diff --git a/docs/config-detail.md b/docs/config-detail.md
index 4960d69..637ad68 100644
--- a/docs/config-detail.md
+++ b/docs/config-detail.md
@@ -1,77 +1,80 @@
# Configuration Detail
-
+
- [TLS](#tls)
- [Athenz n-token](#athenz-n-token)
- [Request filtering](#request-filtering)
- [Admin domain](#admin-domain)
+- [Service domains](#service-domains)
- [Resource mapping](#resource-mapping)
- [Optional API group and resource name control](#optional-api-group-and-resource-name-control)
- [Mapping for non-resources or empty namespace](#mapping-for-non-resources-or-empty-namespace)
-- [P.S.](#ps)
+- [Appendix](#appendix)
-
+
+
+
-
## TLS
![TLS](./assets/tls.png)
-
-### Related configuration
+**Related configuration**
+
1. For garm, `config.yaml`
- ```yaml
- server.tls.ca
- server.tls.cert
- server.tls.key
- athenz.root_ca
- ```
+ ```yaml
+ server.tls.ca
+ server.tls.cert
+ server.tls.key
+
+ athenz.root_ca
+ ```
+
1. For kube-apiserver, `authz.yaml`
- ```yaml
- # https://github.com/kubernetes/apiserver/blob/master/plugin/pkg/authorizer/webhook/webhook.go#L69
- clusters.cluster.certificate-authority
- # https://github.com/kubernetes/apiserver/blob/master/plugin/pkg/authorizer/webhook/webhook.go#L76-L77
- users.user.client-certificate
- users.user.client-key
- ```
+ ```yaml
+ # https://github.com/kubernetes/apiserver/blob/master/plugin/pkg/authorizer/webhook/webhook.go#L69
+ clusters.cluster.certificate-authority
+
+ # https://github.com/kubernetes/apiserver/blob/master/plugin/pkg/authorizer/webhook/webhook.go#L76-L77
+ users.user.client-certificate
+ users.user.client-key
+ ```
+
+**Note**
-
-#### Note
- Garm uses the same server certificate for /authn and /authz.
- If `server.tls.ca` is not set, garm will not verify the client certificate of kube-apiserver.
---
-
## Athenz n-token
-
-### Related configuration
+**Related configuration**
+
```yaml
athenz.auth_header
athenz.token.*
```
-
-#### Note
+**Note**
+
- N-token is for identifying a service (i.e. garm) in Athenz. Athenz then use the pre-configurated policy to check whether the requested access is authenticated.
- N-token is sent to Athenz on every authentication request on the HTTP header with name `athenz.auth_header`.
- If `athenz.token.ntoken_path` is set ([Copper Argos](https://github.com/AthenZ/athenz/blob/master/docs/copper_argos_dev.md)), garm will use the n-token in the file directly.
- - It is better to set `athenz.token.validate_token: true` in this case.
-- If `athenz.token.ntoken_path` is NOT set, garm will handle the token generation and update automatically.
- - As the token is signed by `athenz.token.private_key`, please make sure that the corresponding public key is configurated in Athenz with the same `athenz.token.key_version`.
+ - It is better to set `athenz.token.validate_token: true` in this case.
+ - If `athenz.token.ntoken_path` is NOT set, garm will handle the token generation and update automatically.
+ - As the token is signed by `athenz.token.private_key`, please make sure that the corresponding public key is configurated in Athenz with the same `athenz.token.key_version`.
---
-
## Request filtering
-
-### Related configuration
+**Related configuration**
+
```yaml
map_rule.tld.platform.black_list
map_rule.tld.platform.white_list
@@ -79,76 +82,71 @@ map_rule.tld.platform.white_list
map_rule.tld.service_athenz_domains
```
-
-#### Note
+**Note**
+
- Garm can directly reject kube-apiserver requests without querying Athenz.
- `in black_list AND NOT in white_list` => directly reject
- Support wildcard `*` matching.
---
-
## Admin domain
-
-### Related configuration
+**Related configuration**
+
```yaml
map_rule.tld.platform.admin_access_list
map_rule.tld.platform.admin_athenz_domain
```
-
-#### Note
+**Note**
+
- Garm can map kube-apiserver requests using a separate admin domain in Athenz.
- If the request matches any rules in `map_rule.tld.platform.admin_access_list`, garm will use `map_rule.tld.platform.admin_athenz_domain`.
- Garm will send 1 more request than the number of `map_rule.tld.service_athenz_domains` to Athenz. The kube-apiserver request is allowed if any 1 is allowed in Athenz (OR logic).
- If `service_domain_a` and `service_domain_b` are specified in `map_rule.tld.service_athenz_domains`, it is requested 3 times.
- 1. Athenz resource **with** `service_domain_a` (One of those specified in `map_rule.tld.service_athenz_domains`)
- 1. Athenz resource **with** `service_domain_b` (One of those specified in `map_rule.tld.service_athenz_domains`)
- 1. Athenz resource **without** `map_rule.tld.service_athenz_domains`
+ 1. Athenz resource **with** `service_domain_a` (One of those specified in `map_rule.tld.service_athenz_domains`)
+ 1. Athenz resource **with** `service_domain_b` (One of those specified in `map_rule.tld.service_athenz_domains`)
+ 1. Athenz resource **without** `map_rule.tld.service_athenz_domains`
---
-
## Service domains
-
-### Related configuration
+**Related configuration**
+
```yaml
map_rule.tld.service_athenz_domains
```
-
-#### Note
+**Note**
+
- If the request not matches any rules in `map_rule.tld.platform.admin_access_list`, garm will use `map_rule.tld.service_athenz_domains`.
- Garm will send request number of `map_rule.tld.service_athenz_domains` to Athenz. The kube-apiserver request is allowed if any 1 is allowed in Athenz (OR logic).
- If `service_domain_a` and `service_domain_b` are specified, garm will be requested twice.
---
-
-
## Resource mapping
-
-### Related configuration
+**Related configuration**
+
```yaml
map_rule.tld.platform.resource_mappings
map_rule.tld.platform.verb_mappings
```
-
-#### Note
+**Note**
+
- Garm can map k8s resource to Athenz resource.
- `spec.resourceAttributes.subresource` is appended to `spec.resourceAttributes.resource` before mapping as `spec.resourceAttributes.resource` with format `${resource}.${subresource}`.
---
-
## Optional API group and resource name control
-
-### Related configuration
+**Related configuration**
+
```yaml
map_rule.tld.platform.api_group_control
map_rule.tld.platform.api_group_mappings
@@ -157,17 +155,16 @@ map_rule.tld.platform.resource_name_control
map_rule.tld.platform.resource_name_mappings
```
-
-#### Note
+**Note**
+
- Garm will only map `spec.resourceAttributes.group` and `spec.resourceAttributes.name` in kube-apiserver request body when `map_rule.tld.platform.*_control` is `true`. Else, they will be treated as `""` during mapping.
---
-
## Mapping for non-resources or empty namespace
-
-### Related configuration
+**Related configuration**
+
```yaml
map_rule.tld.platform.empty_namespace
@@ -175,16 +172,16 @@ map_rule.tld.platform.non_resource_api_group
map_rule.tld.platform.non_resource_namespace
```
-
-#### Note
+**Note**
+
- Garm can substitute empty or missing value from kube-apiserver request with above configuration.
- In case of non-resource, resource is equal to `spec.non-resource-attributes.path`.
---
-
-## P.S.
+## Appendix
+
- Above resources,
- - `k8s resource`: ([refer](https://github.com/kubernetes/apiserver/blob/master/plugin/pkg/authorizer/webhook/webhook.go#L165))
- - `resource`: a variable inside garm
- - `Athenz resource`: resource inside policy
+ - `k8s resource`: ([refer](https://github.com/kubernetes/apiserver/blob/master/plugin/pkg/authorizer/webhook/webhook.go#L165))
+ - `resource`: a variable inside garm
+ - `Athenz resource`: resource inside policy
diff --git a/docs/garm-functional-overview.md b/docs/garm-functional-overview.md
index 26befce..1f6e8c2 100644
--- a/docs/garm-functional-overview.md
+++ b/docs/garm-functional-overview.md
@@ -2,123 +2,116 @@
![flowchart](./assets/garm-functional-flowchart.png)
-
+
-- [Garm Functional Overview](#garm-functional-overview)
- - [Parse k8s resources](#parse-k8s-resources)
- - [Map resources](#map-resources)
- - [Subsitute Athenz domain & principal](#subsitute-athenz-domain--principal)
- - [Filter k8s request](#filter-k8s-request)
- - [Select Athenz domain](#select-athenz-domain)
- - [Create Athenz assertion](#create-athenz-assertion)
- - [P.S. during mapping](#ps-during-mapping)
+- [Parse k8s resources](#parse-k8s-resources)
+- [Map resources](#map-resources)
+- [Subsitute Athenz domain \& principal](#subsitute-athenz-domain--principal)
+- [Filter k8s request](#filter-k8s-request)
+- [Select Athenz domain](#select-athenz-domain)
+- [Create Athenz assertion](#create-athenz-assertion)
+ - [during mapping](#during-mapping)
-
+
+
-
## Parse k8s resources
![parse k8s resources](./assets/parse-k8s-resources.png)
1. [K8s authorization attributes](https://kubernetes.io/docs/reference/access-authn-authz/webhook/)
- 1. ResourceAttributes
- - [ResourceAttributes webhook.go](https://github.com/kubernetes/apiserver/blob/master/plugin/pkg/authorizer/webhook/webhook.go#L160-L168)
- - [ResourceAttributes struct](https://github.com/stefanprodan/kubectl-kubesec/blob/master/vendor/k8s.io/api/authorization/v1beta1/types.go#L86-L112)
- 1. NonResourceAttributes
- - [NonResourceAttributes webhook.go](https://github.com/kubernetes/apiserver/blob/master/plugin/pkg/authorizer/webhook/webhook.go#L170-L173)
- - [NonResourceAttributes struct](https://github.com/stefanprodan/kubectl-kubesec/blob/master/vendor/k8s.io/api/authorization/v1beta1/types.go#L114-L122)
+ 1. ResourceAttributes
+ - [ResourceAttributes webhook.go](https://github.com/kubernetes/apiserver/blob/master/plugin/pkg/authorizer/webhook/webhook.go#L160-L168)
+ - [ResourceAttributes struct](https://github.com/stefanprodan/kubectl-kubesec/blob/master/vendor/k8s.io/api/authorization/v1beta1/types.go#L86-L112)
+ 1. NonResourceAttributes
+ - [NonResourceAttributes webhook.go](https://github.com/kubernetes/apiserver/blob/master/plugin/pkg/authorizer/webhook/webhook.go#L170-L173)
+ - [NonResourceAttributes struct](https://github.com/stefanprodan/kubectl-kubesec/blob/master/vendor/k8s.io/api/authorization/v1beta1/types.go#L114-L122)
1. garm resource attributes
- 1. `var namespace, verb, group, resource, name string`
+ 1. `var namespace, verb, group, resource, name string`
-
## Map resources
- verb
- - `config.yaml`, `map_rule.tld.platform.verb_mappings`
- - key-value mapping
+ - `config.yaml`, `map_rule.tld.platform.verb_mappings`
+ - key-value mapping
- resource
- - `config.yaml`, `map_rule.tld.platform.resource_mappings`
- - key-value mapping
+ - `config.yaml`, `map_rule.tld.platform.resource_mappings`
+ - key-value mapping
- group
- - is `""` if `map_rule.tld.platform.api_group_control == false`
- - `config.yaml`, `map_rule.tld.platform.api_group_mappings`
- - key-value mapping
+ - is `""` if `map_rule.tld.platform.api_group_control == false`
+ - `config.yaml`, `map_rule.tld.platform.api_group_mappings`
+ - key-value mapping
- name
- - is `""` if `map_rule.tld.platform.resource_name_control == false`
- - `config.yaml`, `map_rule.tld.platform.resource_name_mappings`
- - key-value mapping
+ - is `""` if `map_rule.tld.platform.resource_name_control == false`
+ - `config.yaml`, `map_rule.tld.platform.resource_name_mappings`
+ - key-value mapping
-
## Subsitute Athenz domain & principal
- Map env. variable in Athenz service domain
- - expectation
- 1. split by `.`
- 1. for each token matches `_.*_`, subsitute with env. variable (except `_namespace_`)
- - example
- - `_k8s_cluster_._namespace_.athenz.service.domain` => `SANDBOX._namespace_.athenz.service.domain`
- + `config.GetActualValue("k8s_cluster") == "SANDBOX"`
+ - expectation
+ 1. split by `.`
+ 1. for each token matches `_.*_`, subsitute with env. variable (except `_namespace_`)
+ - example
+ - `_k8s_cluster_._namespace_.athenz.service.domain` => `SANDBOX._namespace_.athenz.service.domain` + `config.GetActualValue("k8s_cluster") == "SANDBOX"`
- Map namespace in Athenz admain (both admin & service domain)
- - expectation
- 1. subsitute `_namespace_` string in `map_rule.tld.platform.admin_athenz_domain` with garm resource attributes `namespace`
- - example
- - `athenz.domain._namespace_` => `athenz.domain.kaas_namespace`
- + `namespace = kaas_namespace`
+ - expectation
+ 1. subsitute `_namespace_` string in `map_rule.tld.platform.admin_athenz_domain` with garm resource attributes `namespace`
+ - example
+ - `athenz.domain._namespace_` => `athenz.domain.kaas_namespace` + `namespace = kaas_namespace`
- Map k8s user to Athenz principal
- - expectation
- 1. remove `service_account_prefixes`
- 1. subsitute namespace
- 1. subsitute `:`
- 1. if service account, prepend `athenz_service_account_prefix`
- 1. if not service account, prepend `athenz_user_prefix`
- - example
- - `service_a:_namespace_:k8s_user` => `domain_a.k8s.kaas_namespace.k8s_user`
- + `service_account_prefixes = []string{"service_a"}`
- + `athenz_service_account_prefix = "domain_a.k8s."`
- + `namespace = kaas_namespace`
- - `service_b:service_c:k8s_user` => `domain_b.serviceaccount.service_c.k8s_user`
- + `service_account_prefixes = []string{"service_b", "service_c"}`
- + `athenz_service_account_prefix = "domain_b.k8s."`
- - `service_b:k8s_user` => `domain_c.k8s.k8s_user`
- + `service_account_prefixes = []string{"service_a", "service_b"}`
- + `athenz_service_account_prefix = "domain_c.k8s."`
- - `k8s_user` => `user.k8s_user`
- + `athenz_user_prefix = "user."`
+ - expectation
+ 1. remove `service_account_prefixes`
+ 1. subsitute namespace
+ 1. subsitute `:`
+ 1. if service account, prepend `athenz_service_account_prefix`
+ 1. if not service account, prepend `athenz_user_prefix`
+ - example
+ - `service_a:_namespace_:k8s_user` => `domain_a.k8s.kaas_namespace.k8s_user`
+ - \+ `service_account_prefixes = []string{"service_a"}`
+ - \+ `athenz_service_account_prefix = "domain_a.k8s."`
+ - \+ `namespace = kaas_namespace`
+ - `service_b:service_c:k8s_user` => `domain_b.serviceaccount.service_c.k8s_user`
+ - \+ `service_account_prefixes = []string{"service_b", "service_c"}`
+ - \+ `athenz_service_account_prefix = "domain_b.k8s."`
+ - `service_b:k8s_user` => `domain_c.k8s.k8s_user`
+ - \+ `service_account_prefixes = []string{"service_a", "service_b"}`
+ - \+ `athenz_service_account_prefix = "domain_c.k8s."`
+ - `k8s_user` => `user.k8s_user`
+ - \+ `athenz_user_prefix = "user."`
P.S. It may be easier to read the code directly. [createAthenzDomains()](../service/resolver.go#L110), [GetAdminDomain()](../service/resolver.go#280), [BuildDomainsFromNamespace()](../service/resolver.go#125), [PrincipalFromUser()](../service/resolver.go#L187)
-
## Filter k8s request
- `in black_list AND NOT in white_list` => directly reject
- - `config.yaml`, `map_rule.tld.platform.black_list` & `map_rule.tld.platform.white_list`
+ - `config.yaml`, `map_rule.tld.platform.black_list` & `map_rule.tld.platform.white_list`
- Matching logic
- - create rule RegExp for matching
- - ![garm resource matching](./assets/garm-resource-matching.png)
- - Garm resource attribute is serialized before matching with the rule RegExp.
+ - create rule RegExp for matching
+ - ![garm resource matching](./assets/garm-resource-matching.png)
+ - Garm resource attribute is serialized before matching with the rule RegExp.
- Example
- - `RequestInfo{ Verb: "get", Namespace: "kube-system", APIGroup: "*", Resource: "secrets", Name: "alertmanager"}` => check with Athenz
- - black_list contains `RequestInfo{ Verb: "*", Namespace: "kube-system", APIGroup: "*", Resource: "*", Name: "*"}`.
- - white_list contains `RequestInfo{ Verb: "get", Namespace: "kube-system", APIGroup: "*", Resource: "secrets", Name: "alertmanager"}`.
- - `RequestInfo{ Verb: "get", Namespace: "kube-system", APIGroup: "*", Resource: "secrets", Name: "my-secret"}` => directly reject
- - black_list contains `RequestInfo{ Verb: "*", Namespace: "kube-system", APIGroup: "*", Resource: "*", Name: "*"}`.
- - white_list **ONLY** contains `RequestInfo{ Verb: "get", Namespace: "kube-system", APIGroup: "*", Resource: "secrets", Name: "alertmanager"}`.
-
-
+ - `RequestInfo{ Verb: "get", Namespace: "kube-system", APIGroup: "*", Resource: "secrets", Name: "alertmanager"}` => check with Athenz
+ - black_list contains `RequestInfo{ Verb: "*", Namespace: "kube-system", APIGroup: "*", Resource: "*", Name: "*"}`.
+ - white_list contains `RequestInfo{ Verb: "get", Namespace: "kube-system", APIGroup: "*", Resource: "secrets", Name: "alertmanager"}`.
+ - `RequestInfo{ Verb: "get", Namespace: "kube-system", APIGroup: "*", Resource: "secrets", Name: "my-secret"}` => directly reject
+ - black_list contains `RequestInfo{ Verb: "*", Namespace: "kube-system", APIGroup: "*", Resource: "*", Name: "*"}`.
+ - white_list **ONLY** contains `RequestInfo{ Verb: "get", Namespace: "kube-system", APIGroup: "*", Resource: "secrets", Name: "alertmanager"}`.
+
## Select Athenz domain
+
- `in admin_access_list` => use admin domain
- - `config.yaml`, `map_rule.tld.platform.admin_access_list`
+ - `config.yaml`, `map_rule.tld.platform.admin_access_list`
- Matching logic
- - same as above
+ - same as above
-
## Create Athenz assertion
-###### P.S. during mapping
+### during mapping
+
![optional api group and resource name](./assets/optional-api-group-and-resource-name.png)
- Athenz service domain
- - ![create athenz assertion on service domain](./assets/create-athenz-assertion-on-service-domain.png)
+ - ![create athenz assertion on service domain](./assets/create-athenz-assertion-on-service-domain.png)
- Athenz admin domain (2 requests to Athenz, OR logic, any one is allowed implies the action is allowed.)
- - ![create athenz assertion on admin domain](./assets/create-athenz-assertion-on-admin-domain.png)
-
+ - ![create athenz assertion on admin domain](./assets/create-athenz-assertion-on-admin-domain.png)
diff --git a/docs/graceful-shutdown.md b/docs/graceful-shutdown.md
index 88dc3f0..e11245c 100644
--- a/docs/graceful-shutdown.md
+++ b/docs/graceful-shutdown.md
@@ -1,3 +1,3 @@
# graceful shutdown
-reference: https://github.com/AthenZ/authorization-proxy/blob/master/docs/graceful-shutdown.md
+reference:
diff --git a/docs/installation/01. setup-nodes.md b/docs/installation/01. setup-nodes.md
index e2f30cf..bdf7e9c 100644
--- a/docs/installation/01. setup-nodes.md
+++ b/docs/installation/01. setup-nodes.md
@@ -1,19 +1,19 @@
# Setup k8s nodes
-
+
-- [Setup k8s nodes](#setup-k8s-nodes)
- - [Prepare linux env. for installing k8s](#prepare-linux-env-for-installing-k8s)
- - [Install docker and k8s](#install-docker-and-k8s)
- - [[master only] Config master node](#master-only-config-master-node)
- - [Config the cluster](#config-the-cluster)
- - [Join the cluster](#join-the-cluster)
- - [Config local machine (host to remote control k8s)](#config-local-machine-host-to-remote-control-k8s)
+- [Prepare linux env. for installing k8s](#prepare-linux-env-for-installing-k8s)
+- [Install docker and k8s](#install-docker-and-k8s)
+- [\[master only\] Config master node](#master-only-config-master-node)
+- [Config the cluster](#config-the-cluster)
+- [Join the cluster](#join-the-cluster)
+- [Config local machine (host to remote control k8s)](#config-local-machine-host-to-remote-control-k8s)
-
+
+
-
## Prepare linux env. for installing k8s
+
```bash
#!/bin/sh
sudo systemctl stop firewalld
@@ -54,8 +54,8 @@ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
sudo reboot
```
-
## Install docker and k8s
+
```bash
#!/bin/sh
sudo yum remove -y docker docker-common docker-selinux docker-engine kubelet kubeadm kubectl
@@ -108,8 +108,8 @@ sudo /sbin/sysctl -w net.ipv4.ip_forward=1
sudo kubeadm reset
```
-
## [master only] Config master node
+
```bash
sudo kubeadm config images pull
sudo kubeadm init --pod-network-cidr=192.168.0.0/16
@@ -138,8 +138,8 @@ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
```
-
## Config the cluster
+
```bash
# install essential k8s services to cluster
# wait for all k8s component completely started, else the following commands will fail
@@ -147,15 +147,15 @@ kubectl apply -f https://docs.projectcalico.org/v3.1/getting-started/kubernetes/
kubectl apply -f https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml
```
-
## Join the cluster
+
```bash
# run the `kubeadm join` command on nodes
kubeadm join {ip}:6443 --token {token} --discovery-token-ca-cert-hash {hash}
```
-
## Config local machine (host to remote control k8s)
+
```bash
# paste the content of `/etc/kubernetes/admin.conf` from master node
cat > ~/.kube/config
diff --git a/docs/installation/02. install-garm.md b/docs/installation/02. install-garm.md
index ea04664..9b01956 100644
--- a/docs/installation/02. install-garm.md
+++ b/docs/installation/02. install-garm.md
@@ -1,24 +1,27 @@
# Install garm
-
+
- [Prepare garm configuration](#prepare-garm-configuration)
- - [Examples](#examples)
+ - [Examples](#examples)
- [Prepare domain and service](#prepare-domain-and-service)
- [Prepare Athenz and garm certificate](#prepare-athenz-and-garm-certificate)
- - [Get root CA certificate and save as "Athenz root CA certificate"](#get-root-ca-certificate-and-save-as-athenz-root-ca-certificate)
- - [Create garm certificate](#create-garm-certificate)
- - [Add garm certificates as k8s secret](#add-garm-certificates-as-k8s-secret)
+ - [Get root CA certificate and save as "Athenz root CA certificate"](#get-root-ca-certificate-and-save-as-athenz-root-ca-certificate)
+ - [Create garm certificate](#create-garm-certificate)
+ - [Add garm certificates as k8s secret](#add-garm-certificates-as-k8s-secret)
- [Apply the garm configuration](#apply-the-garm-configuration)
-
+
+
-
## Prepare garm configuration
+
Below files are under [/k8s/\*.yaml](../../k8s)
### Examples
+
1. [garm-config.yaml](../../k8s/garm-config.yaml)
+
```yaml
token:
... (Omitted) ...
@@ -41,7 +44,9 @@ Below files are under [/k8s/\*.yaml](../../k8s)
metadata:
... (Omitted) ...
```
+
1. [garm-extapi.yaml](../../k8s/garm-extapi.yaml)
+
```yaml
apiVersion: v1
data:
@@ -50,31 +55,35 @@ Below files are under [/k8s/\*.yaml](../../k8s)
athenz-domain: athenz.garm.user
service-name: garm-service
```
-1. [deployments.yaml](../../k8s/deployments.yaml)
+1. [deployments.yaml](../../k8s/deployments.yaml)
- comment out configurations not in use
- ```yaml
- spec:
- template:
+
+ ```yaml
spec:
- containers:
- - env:
- ... (Omitted) ...
+ template:
+ spec:
+ containers:
+ - env:
+ ... (Omitted) ...
- # - name: ca
- # valueFrom:
- # configMapKeyRef:
- # key: ca-public-key
- # name: garm-extapi
+ # - name: ca
+ # valueFrom:
+ # configMapKeyRef:
+ # key: ca-public-key
+ # name: garm-extapi
+
+ ... (Omitted) ...
+ ```
- ... (Omitted) ...
- ```
- modify Docker Registry URL
- ```yaml
- image: docker.io/athenz/garm:latest
- ```
+
+ ```yaml
+ image: docker.io/athenz/garm:latest
+ ```
1. [service.yaml](../../k8s/service.yaml)
+
```yaml
# please make sure the IP works in your k8s cluster
# reminder this IP, it will be used later
@@ -82,9 +91,10 @@ Below files are under [/k8s/\*.yaml](../../k8s)
clusterIP: 10.96.0.11
```
-
## Prepare domain and service
+
1. Create athenz domain
+
```bash
# sample domains
@@ -95,24 +105,25 @@ Below files are under [/k8s/\*.yaml](../../k8s)
# garm sub-domain for k8s user operation
athenz.garm.user
```
+
1. Create service
1. Generate key pair for the service and register public key to Athenz
1. Save the private key as `athenz.key`
-
## Prepare Athenz and garm certificate
-
+
### Get root CA certificate and save as "Athenz root CA certificate"
Root CA depends on the Athenz server which Garm connects to. For example:
-```
+
+```bash
# Cybertrust
wget 'https://www.cybertrust.ne.jp/sureserver/download/root_ca/BCTRoot.txt' -O ./athenz_root_ca.key
# DigiCert
wget 'https://dl.cacerts.digicert.com/DigiCertHighAssuranceEVRootCA.crt' -O ./athenz_root_ca.key
```
-
### Create garm certificate
+
```bash
# CA
openssl genrsa -out rootCA.key 4096
@@ -141,8 +152,8 @@ openssl x509 -in garm.crt -text -noout
# openssl base64 -in garm.crt | tr -d '\n'; echo ''
```
-
### Add garm certificates as k8s secret
+
```bash
# private key for login athenz
ATHENZ_PRIVATE_KEY='./athenz.key'
@@ -160,8 +171,8 @@ kubectl create secret generic garm-secret-ca -n kube-public \
--from-file=garm-server-cert.pem="${GARM_SERVER_CERT}"
```
-
## Apply the garm configuration
+
```bash
# please execute with the same order
kubectl apply -f garm-extapi.yaml
diff --git a/docs/installation/03. config-k8s-in-webhook-mode.md b/docs/installation/03. config-k8s-in-webhook-mode.md
index 68d8d92..3f887d4 100644
--- a/docs/installation/03. config-k8s-in-webhook-mode.md
+++ b/docs/installation/03. config-k8s-in-webhook-mode.md
@@ -1,52 +1,52 @@
# Config k8s in webhook mode and use garm
-
+
-- [Config k8s in webhook mode and use garm](#config-k8s-in-webhook-mode-and-use-garm)
- - [Single master](#single-master)
- - [Prepare required files](#prepare-required-files)
- - [Config master node](#config-master-node)
- - [Check garm can get webhook request](#check-garm-can-get-webhook-request)
- - [Extra](#extra)
- - [Using ConfigMap (single master will not work)](#using-configmap-single-master-will-not-work)
- - [Add webhook user certificate as k8s secret](#add-webhook-user-certificate-as-k8s-secret)
- - [[master node] Set apiserver to webhook mode (below config is not tested)](#master-node-set-apiserver-to-webhook-mode-below-config-is-not-tested)
+- [Single master](#single-master)
+ - [Prepare required files](#prepare-required-files)
+ - [Config master node](#config-master-node)
+- [Check garm can get webhook request](#check-garm-can-get-webhook-request)
+- [Extra](#extra)
+ - [Using ConfigMap (single master will not work)](#using-configmap-single-master-will-not-work)
+ - [Add webhook user certificate as k8s secret](#add-webhook-user-certificate-as-k8s-secret)
+ - [\[master node\] Set apiserver to webhook mode (below config is not tested)](#master-node-set-apiserver-to-webhook-mode-below-config-is-not-tested)
-
+
+
-
## Single master
-
### Prepare required files
+
- File from [previous tutorial](./02.%20install-garm.md)
- - `user.key`
- - `user.crt`
- - `rootCA.crt` (rename to `garm-ca.crt`)
+ - `user.key`
+ - `user.crt`
+ - `rootCA.crt` (rename to `garm-ca.crt`)
- `authz.yaml`
- - update the IP address below (`10.96.0.11`) to garm service IP ([service.yaml](../../k8s/service.yaml))
- - sample file content
- ```yaml
- clusters:
- - name: kubernetes
- cluster:
- certificate-authority: /etc/kubernetes/pki/garm-ca.crt
- server: https://10.96.0.11/authz
- users:
- - name: my-api-server
- user:
- client-certificate: /etc/kubernetes/pki/user.crt
- client-key: /etc/kubernetes/pki/user.key
- current-context: webhook
- contexts:
- - context:
- cluster: kubernetes
- user: my-api-sever
- name: webhook
- ```
-
-
+ - update the IP address below (`10.96.0.11`) to garm service IP ([service.yaml](../../k8s/service.yaml))
+ - sample file content
+
+ ```yaml
+ clusters:
+ - name: kubernetes
+ cluster:
+ certificate-authority: /etc/kubernetes/pki/garm-ca.crt
+ server: https://10.96.0.11/authz
+ users:
+ - name: my-api-server
+ user:
+ client-certificate: /etc/kubernetes/pki/user.crt
+ client-key: /etc/kubernetes/pki/user.key
+ current-context: webhook
+ contexts:
+ - context:
+ cluster: kubernetes
+ user: my-api-sever
+ name: webhook
+ ```
+
### Config master node
+
```bash
# move the requried files to apiserver mount point
sudo mv *.key *.crt /etc/kubernetes/pki/
@@ -62,8 +62,8 @@ sudo vim /etc/kubernetes/manifests/kube-apiserver.yaml
# wait for apiserver to restart automatically
```
-
## Check garm can get webhook request
+
```bash
# create a dummy user
kubectl config delete-context testing-garm
@@ -81,11 +81,10 @@ kubectl config use-context kubernetes-admin@kubernetes
kubectl logs garm-7bf5bc6f9d-b5l5c -n kube-public
```
-
## Extra
-
### Using ConfigMap (single master will not work)
+
```bash
cat | kubectl apply -f - <<'EOF'
apiVersion: v1
@@ -121,8 +120,8 @@ EOF
kubectl get configmap authz-config -n kube-system -o yaml | less
```
-
### Add webhook user certificate as k8s secret
+
```bash
WEBHOOK_USER_KEY='./user.key'
WEBHOOK_USER_CERT='./user.crt'
@@ -143,9 +142,10 @@ kubectl get secret webhook-user -n kube-system -o yaml | less
kubectl get secret garm-root-ca -n kube-system -o yaml | less
```
-
#### [master node] Set apiserver to webhook mode (below config is not tested)
+
`sudo vim /etc/kubernetes/manifests/kube-apiserver.yaml`
+
```yaml
- --authorization-mode=Node,RBAC,Webhook
- --authorization-webhook-config-file=/etc/kubernetes/authz.yaml
@@ -173,5 +173,4 @@ kubectl get secret garm-root-ca -n kube-system -o yaml | less
secret:
defaultMode: 420
secretName: garm-root-ca
-
```
diff --git a/main.go b/main.go
index 7c0903e..50daa59 100644
--- a/main.go
+++ b/main.go
@@ -31,7 +31,7 @@ import (
"github.com/pkg/errors"
)
-// Version is set by the build command via LDFLAGS
+// Version is set by the build command via LDFLAGS'.
var Version string
// params is the data model for Garm command line arguments.
diff --git a/router/router_test.go b/router/router_test.go
index 0f1e97f..feb11ba 100644
--- a/router/router_test.go
+++ b/router/router_test.go
@@ -35,10 +35,10 @@ import (
"github.com/kpango/glg"
)
-// glgMutex prevent race condition on glg
+// glgMutex prevent race condition on glg.
var glgMutex = &sync.Mutex{}
-// dummyHandler is a mock implement for handler.Handler
+// dummyHandler is a mock implement for handler.Handler.
type dummyHandler struct {
responseValue string
}
@@ -118,7 +118,7 @@ func TestNewServeMux(t *testing.T) {
want = "Authenticate response"
handler.responseValue = want
recorder = httptest.NewRecorder()
- request, err = http.NewRequest(http.MethodPost, "/authn", nil)
+ request, err = http.NewRequestWithContext(context.Background(), http.MethodPost, "/authn", nil)
if err != nil {
return
}
@@ -137,7 +137,7 @@ func TestNewServeMux(t *testing.T) {
want = "Authorize response"
handler.responseValue = want
recorder = httptest.NewRecorder()
- request, err = http.NewRequest(http.MethodPost, "/authz", nil)
+ request, err = http.NewRequestWithContext(context.Background(), http.MethodPost, "/authz", nil)
if err != nil {
return
}
@@ -229,7 +229,7 @@ func Test_routing(t *testing.T) {
h: handlerFunc,
},
checkFunc: func(server http.Handler) error {
- request, err := http.NewRequest(http.MethodGet, "/", nil)
+ request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
if err != nil {
return err
}
@@ -273,7 +273,7 @@ func Test_routing(t *testing.T) {
glgMutex.Lock()
glg.Get().SetMode(glg.NONE)
- request, err := http.NewRequest(http.MethodGet, "/", nil)
+ request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
if err != nil {
return err
}
@@ -311,7 +311,7 @@ func Test_routing(t *testing.T) {
h: handlerFunc,
},
checkFunc: func(server http.Handler) error {
- request, err := http.NewRequest(http.MethodGet, "/", nil)
+ request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
if err != nil {
return err
}
@@ -351,7 +351,7 @@ func Test_routing(t *testing.T) {
h: handlerFunc,
},
checkFunc: func(server http.Handler) error {
- request, err := http.NewRequest(http.MethodOptions, "/", nil)
+ request, err := http.NewRequestWithContext(context.Background(), http.MethodOptions, "/", nil)
if err != nil {
return err
}
@@ -393,7 +393,7 @@ func Test_routing(t *testing.T) {
},
checkFunc: func(server http.Handler) error {
for _, method := range []string{http.MethodGet, http.MethodPost} {
- request, err := http.NewRequest(method, "/", nil)
+ request, err := http.NewRequestWithContext(context.Background(), method, "/", nil)
if err != nil {
return err
}
@@ -442,7 +442,7 @@ func Test_routing(t *testing.T) {
errorBuffer := new(bytes.Buffer)
glg.Get().SetMode(glg.WRITER).SetWriter(errorBuffer)
- request, err := http.NewRequest(http.MethodGet, "/", nil)
+ request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
if err != nil {
return err
}
@@ -486,7 +486,7 @@ func Test_routing(t *testing.T) {
errorBuffer := new(bytes.Buffer)
glg.Get().SetMode(glg.WRITER).SetWriter(errorBuffer)
- request, err := http.NewRequest(http.MethodGet, "/", nil)
+ request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
if err != nil {
return err
}
@@ -540,7 +540,7 @@ func Test_routing(t *testing.T) {
rpr, rpw := io.Pipe()
rpw.Close()
rpr.Close()
- request, err := http.NewRequest(http.MethodGet, "/", rpr)
+ request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/", rpr)
if err != nil {
return err
}
@@ -585,7 +585,7 @@ func Test_routing(t *testing.T) {
h: handlerFunc,
},
checkFunc: func(server http.Handler) error {
- request, err := http.NewRequest(http.MethodGet, "/", nil)
+ request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
if err != nil {
return err
}
@@ -780,7 +780,7 @@ func Test_recoverWrap(t *testing.T) {
h: handlerFunc,
},
checkFunc: func(server http.Handler) error {
- request, err := http.NewRequest(http.MethodGet, "/", nil)
+ request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
if err != nil {
return err
}
@@ -825,7 +825,7 @@ func Test_recoverWrap(t *testing.T) {
errorBuffer := new(bytes.Buffer)
glg.Get().SetMode(glg.WRITER).SetWriter(errorBuffer)
- request, err := http.NewRequest(http.MethodGet, "/", nil)
+ request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
if err != nil {
return err
}
diff --git a/service/athenz.go b/service/athenz.go
index 46f2780..31855fd 100755
--- a/service/athenz.go
+++ b/service/athenz.go
@@ -34,7 +34,7 @@ type Athenz interface {
AthenzAuthenticator(http.ResponseWriter, *http.Request) error
}
-// Wrapper for Athenz HTTP request handlers
+// Wrapper for Athenz HTTP request handlers.
type athenz struct {
// authConfig is the shared configuration for the HTTP handlers.
authConfig config.Athenz
diff --git a/service/athenz_test.go b/service/athenz_test.go
index 8cad6be..cb0874b 100644
--- a/service/athenz_test.go
+++ b/service/athenz_test.go
@@ -35,19 +35,19 @@ import (
authz "k8s.io/api/authorization/v1beta1"
)
-// dummyLogger is a mock implementation for webhook.Logger
+// dummyLogger is a mock implementation for webhook.Logger.
type dummyLogger string
-// Println is mock method for webhook.Logger interface
+// Println is mock method for webhook.Logger interface.
func (dummyLogger) Println(args ...interface{}) {}
-// Printf is mock method for webhook.Logger interface
+// Printf is mock method for webhook.Logger interface.
func (dummyLogger) Printf(format string, args ...interface{}) {}
-// dummyLogger is a mock implementation for webhook.ResourceMapper and webhook.UserMapper
+// dummyLogger is a mock implementation for webhook.ResourceMapper and webhook.UserMapper.
type dummyMapper string
-// MapResource is mock method for webhook.ResourceMapper interface
+// MapResource is mock method for webhook.ResourceMapper interface.
func (dummyMapper) MapResource(ctx context.Context, spec authz.SubjectAccessReviewSpec) (principal string, checks []webhook.AthenzAccessCheck, err error) {
principal = "principal"
checks = []webhook.AthenzAccessCheck{
@@ -64,7 +64,7 @@ func (dummyMapper) MapResource(ctx context.Context, spec authz.SubjectAccessRevi
return
}
-// MapUser is mock method for webhook.UserMapper interface
+// MapUser is mock method for webhook.UserMapper interface.
func (dummyMapper) MapUser(ctx context.Context, domain, service string) (authn.UserInfo, error) {
return authn.UserInfo{
Username: "username",
diff --git a/service/resolver.go b/service/resolver.go
index a101eb2..00d9bf2 100755
--- a/service/resolver.go
+++ b/service/resolver.go
@@ -127,7 +127,7 @@ func (r *resolve) MapK8sResourceAthenzResource(k8sRes string) string {
// do the following for each athenzDomains
// split it with ".";
// for each token, if it match /^_.*_$/ but not "_namespace_", replace the token with config.GetActualValue(token);
-// and then return the processed value
+// and then return the processed value.
func (r *resolve) createAthenzDomains(athenzDomains []string) []string {
if len(athenzDomains) == 0 {
return athenzDomains
@@ -157,7 +157,8 @@ func (r *resolve) BuildDomainsFromNamespace(namespace string) []string {
return r.buildAthenzDomain(r.athenzDomains, namespace)
}
-// BuildServiceAccountPrefixFromNamespace returns domains by processing AthenzServiceAccountPrefix.
+// BuildServiceAccountPrefixFromNamespace returns domains by processing AthenzServiceAccountPrefix.
+//
// if namespace != "", replace `/ = .`, then `.. => -`, then replace "_namespace_" in AthenzServiceAccountPrefix with namespace;
// else replace "._namespace_" in AthenzServiceAccountPrefix with namespace;
// trim ".", then "-", then ":"
@@ -223,17 +224,17 @@ func (r *resolve) MapResourceName(name string) string {
return name
}
-// GetEmptyNamespace returns cfg.EmptyNamespace
+// GetEmptyNamespace returns cfg.EmptyNamespace.
func (r *resolve) GetEmptyNamespace() string {
return r.cfg.EmptyNamespace
}
-// GetNonResourceGroup returns cfg.NonResourceAPIGroup
+// GetNonResourceGroup returns cfg.NonResourceAPIGroup.
func (r *resolve) GetNonResourceGroup() string {
return r.cfg.NonResourceAPIGroup
}
-// GetNonResourceNamespace returns cfg.NonResourceNamespace
+// GetNonResourceNamespace returns cfg.NonResourceNamespace.
func (r *resolve) GetNonResourceNamespace() string {
return r.cfg.NonResourceNamespace
}
@@ -339,7 +340,7 @@ func (r *resolve) IsAllowed(verb, namespace, apiGroup, resource, name string) bo
return true
}
-// IsAdminAccess returns true, if any admin access in config match
+// IsAdminAccess returns true, if any admin access in config match.
func (r *resolve) IsAdminAccess(verb, namespace, apiGroup, resource, name string) bool {
var ok bool
for _, admin := range r.cfg.AdminAccessList {
diff --git a/service/resolver_test.go b/service/resolver_test.go
index 153f9e9..8e5f8c6 100644
--- a/service/resolver_test.go
+++ b/service/resolver_test.go
@@ -506,8 +506,9 @@ func Test_resolve_createAthenzDomains(t *testing.T) {
}
r := &resolve{
- cfg: tt.fields.cfg,
- athenzDomains: tt.fields.athenzDomains,
+ cfg: tt.fields.cfg,
+ athenzDomains: tt.fields.athenzDomains,
+ athenzSAPrefix: tt.fields.athenzSAPrefix,
}
if got := r.createAthenzDomains(tt.args.athenzDomains); !reflect.DeepEqual(got, tt.want) {
t.Errorf("resolve.createAthenzDomains() = %v, want %v", got, tt.want)
diff --git a/service/server.go b/service/server.go
index 3e11dd2..e169713 100755
--- a/service/server.go
+++ b/service/server.go
@@ -55,18 +55,18 @@ type server struct {
}
const (
- // ContentType represents a HTTP header name "Content-Type"
+ // ContentType represents a HTTP header name "Content-Type".
ContentType = "Content-Type"
- // TextPlain represents a HTTP content type "text/plain"
+ // TextPlain represents a HTTP content type "text/plain".
TextPlain = "text/plain"
- // CharsetUTF8 represents a UTF-8 charset for HTTP response "charset=UTF-8"
+ // CharsetUTF8 represents a UTF-8 charset for HTTP response "charset=UTF-8".
CharsetUTF8 = "charset=UTF-8"
)
var (
- // ErrContextClosed represents the error that the context is closed
+ // ErrContextClosed represents the error that the context is closed.
ErrContextClosed = errors.New("context Closed")
)
diff --git a/service/server_test.go b/service/server_test.go
index e1a5a60..43e40d8 100644
--- a/service/server_test.go
+++ b/service/server_test.go
@@ -180,10 +180,15 @@ func Test_server_ListenAndServe(t *testing.T) {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
checkSrvRunning := func(addr string) error {
- res, err := http.DefaultClient.Get(addr)
+ req, err := http.NewRequestWithContext(context.Background(), "GET", addr, nil)
if err != nil {
return err
}
+ res, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return err
+ }
+ defer res.Body.Close()
if res.StatusCode != 200 {
return fmt.Errorf("Response status code invalid, %v", res.StatusCode)
}
@@ -284,10 +289,15 @@ func Test_server_ListenAndServe(t *testing.T) {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
checkSrvRunning := func(addr string) error {
- res, err := http.DefaultClient.Get(addr)
+ req, err := http.NewRequestWithContext(context.Background(), "GET", addr, nil)
+ if err != nil {
+ return err
+ }
+ res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
+ defer res.Body.Close()
if res.StatusCode != 200 {
return fmt.Errorf("Response status code invalid, %v", res.StatusCode)
}
@@ -388,10 +398,15 @@ func Test_server_ListenAndServe(t *testing.T) {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
checkSrvRunning := func(addr string) error {
- res, err := http.DefaultClient.Get(addr)
+ req, err := http.NewRequestWithContext(context.Background(), "GET", addr, nil)
if err != nil {
return err
}
+ res, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return err
+ }
+ defer res.Body.Close()
if res.StatusCode != 200 {
return fmt.Errorf("Response status code invalid, %v", res.StatusCode)
}
@@ -468,7 +483,6 @@ func Test_server_hcShutdown(t *testing.T) {
type fields struct {
srv *http.Server
srvRunning bool
- hcsrv *http.Server
hcrunning bool
cfg config.Server
pwt time.Duration
@@ -547,7 +561,6 @@ func Test_server_hcShutdown(t *testing.T) {
func Test_server_apiShutdown(t *testing.T) {
type fields struct {
- srv *http.Server
srvRunning bool
hcsrv *http.Server
hcrunning bool
@@ -703,6 +716,7 @@ func Test_server_handleHealthCheckRequest(t *testing.T) {
},
checkFunc: func() error {
result := rw.Result()
+ defer result.Body.Close()
if header := result.StatusCode; header != http.StatusOK {
return fmt.Errorf("Header is not correct, got: %v", header)
}
diff --git a/service/token.go b/service/token.go
index 23caba0..dde96a0 100755
--- a/service/token.go
+++ b/service/token.go
@@ -48,7 +48,7 @@ type token struct {
}
var (
- // ErrTokenNotFound represents the error that the token is not found
+ // ErrTokenNotFound represents the error that the token is not found.
ErrTokenNotFound = errors.New("Error:\ttoken not found")
)