├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── CONTRIBUTING.md
├── Dockerfile
├── FEATURES.md
├── LICENSE.md
├── README.md
├── USAGE-v5.1.md
├── USAGE-v5.2.md
├── USAGE-v5.3.md
├── code_of_conduct.md
├── contrib
├── README.md
├── app-protect
│ ├── Dockerfile
│ ├── README.md
│ └── src
│ │ ├── requirements.txt
│ │ ├── server.py
│ │ └── start.sh
├── devportal
│ └── redocly
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ └── src
│ │ ├── requirements.txt
│ │ ├── server.py
│ │ └── start.sh
├── docker-compose
│ ├── README.md
│ ├── docker-compose.yaml
│ └── nginx-dapi.sh
├── gitops-examples
│ ├── jkws.json
│ ├── v5.1
│ │ ├── apigw.nginx.lab.crt
│ │ ├── apigw.nginx.lab.key
│ │ ├── client.cert.pem
│ │ ├── client.key.pem
│ │ ├── nap-policy-xss-allowed.json
│ │ ├── nap-policy-xss-blocked-bot-allowed.json
│ │ ├── nap-policy-xss-blocked.json
│ │ ├── testcert.chain
│ │ ├── testcert.crt
│ │ ├── testcert.key
│ │ ├── testcert2.chain
│ │ ├── testcert2.crt
│ │ └── testcert2.key
│ ├── v5.2
│ │ ├── apigw.nginx.lab.crt
│ │ ├── apigw.nginx.lab.key
│ │ ├── client.cert.pem
│ │ ├── client.key.pem
│ │ ├── nap-policy-xss-allowed.json
│ │ ├── nap-policy-xss-blocked-bot-allowed.json
│ │ ├── nap-policy-xss-blocked.json
│ │ ├── testcert.chain
│ │ ├── testcert.crt
│ │ ├── testcert.key
│ │ ├── testcert2.chain
│ │ ├── testcert2.crt
│ │ └── testcert2.key
│ └── v5.3
│ │ ├── apigw.nginx.lab.crt
│ │ ├── apigw.nginx.lab.key
│ │ ├── client.cert.pem
│ │ ├── client.key.pem
│ │ ├── nap-policy-xss-allowed.json
│ │ ├── nap-policy-xss-blocked-bot-allowed.json
│ │ ├── nap-policy-xss-blocked.json
│ │ ├── testcert.chain
│ │ ├── testcert.crt
│ │ ├── testcert.key
│ │ ├── testcert2.chain
│ │ ├── testcert2.crt
│ │ └── testcert2.key
├── kubernetes
│ ├── README.md
│ └── nginx-declarative-api.yaml
└── postman
│ ├── NGINX Declarative API.postman_collection.json
│ └── README.md
├── etc
└── config.toml
├── src
├── NcgConfig.py
├── NcgRedis.py
├── V5_1_CreateConfig.py
├── V5_1_NginxConfigDeclaration.py
├── V5_2_CreateConfig.py
├── V5_2_NginxConfigDeclaration.py
├── V5_3_CreateConfig.py
├── V5_3_NginxConfigDeclaration.py
├── main.py
├── requirements.txt
├── v5_1
│ ├── APIGateway.py
│ ├── DeclarationPatcher.py
│ ├── DevPortal.py
│ ├── GitOps.py
│ ├── MiscUtils.py
│ ├── NAPUtils.py
│ ├── NGINXOneOutput.py
│ ├── NGINXOneUtils.py
│ ├── NIMUtils.py
│ ├── NMSOutput.py
│ └── OpenAPIParser.py
├── v5_2
│ ├── APIGateway.py
│ ├── DeclarationPatcher.py
│ ├── DevPortal.py
│ ├── GitOps.py
│ ├── MiscUtils.py
│ ├── NAPUtils.py
│ ├── NGINXOneOutput.py
│ ├── NGINXOneUtils.py
│ ├── NIMOutput.py
│ ├── NIMUtils.py
│ └── OpenAPIParser.py
└── v5_3
│ ├── APIGateway.py
│ ├── Asynchronous.py
│ ├── DeclarationPatcher.py
│ ├── DevPortal.py
│ ├── GitOps.py
│ ├── MiscUtils.py
│ ├── NAPUtils.py
│ ├── NGINXOneOutput.py
│ ├── NGINXOneUtils.py
│ ├── NIMOutput.py
│ ├── NIMUtils.py
│ └── OpenAPIParser.py
└── templates
├── v5.1
├── apigateway.tmpl
├── authn
│ ├── client
│ │ ├── jwks.tmpl
│ │ ├── jwt.tmpl
│ │ └── mtls.tmpl
│ └── server
│ │ ├── mtls.tmpl
│ │ └── token.tmpl
├── authz
│ └── client
│ │ ├── jwt-authz-map.tmpl
│ │ └── jwt.tmpl
├── configmap.tmpl
├── devportal
│ └── backstage.tmpl
├── http.tmpl
├── logformat.tmpl
├── misc
│ ├── resolver.tmpl
│ ├── upstream-http.tmpl
│ └── upstream-stream.tmpl
├── nginx-conf
│ ├── mime.types
│ └── nginx.conf
├── stream.tmpl
└── visibility
│ └── moesif
│ ├── http.tmpl
│ └── server.tmpl
├── v5.2
├── apigateway.tmpl
├── authn
│ ├── client
│ │ ├── jwks.tmpl
│ │ ├── jwt.tmpl
│ │ └── mtls.tmpl
│ └── server
│ │ ├── mtls.tmpl
│ │ └── token.tmpl
├── authz
│ └── client
│ │ ├── jwt-authz-map.tmpl
│ │ └── jwt.tmpl
├── devportal
│ └── backstage.tmpl
├── http.tmpl
├── logformat.tmpl
├── misc
│ ├── resolver.tmpl
│ ├── upstream-http.tmpl
│ └── upstream-stream.tmpl
├── nginx-conf
│ ├── license-key.tmpl
│ ├── mime.types
│ └── nginx.conf
├── stream.tmpl
└── visibility
│ └── moesif
│ ├── http.tmpl
│ └── server.tmpl
└── v5.3
├── apigateway.tmpl
├── authn
├── client
│ ├── jwks.tmpl
│ ├── jwt.tmpl
│ └── mtls.tmpl
└── server
│ ├── mtls.tmpl
│ └── token.tmpl
├── authz
└── client
│ ├── jwt-authz-map.tmpl
│ └── jwt.tmpl
├── devportal
└── backstage.tmpl
├── http.tmpl
├── logformat.tmpl
├── misc
├── resolver.tmpl
├── upstream-http.tmpl
└── upstream-stream.tmpl
├── nginx-conf
├── license-key.tmpl
├── mime.types
└── nginx.conf
├── stream.tmpl
└── visibility
└── moesif
├── http.tmpl
└── server.tmpl
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Any private crt and keys #
2 | ############################
3 | #*.crt
4 | #*.key
5 | *~
6 | \#*
7 |
8 | # OS Specific #
9 | ###############
10 | Thumbs.db
11 | .DS_Store
12 | .vscode
13 |
14 | # Logs #
15 | ########
16 | *.log
17 |
18 | # Additional dirs #
19 | ###################
20 | =======
21 | /.idea/
22 | /src/__pycache__/
23 | /src/v5_1/__pycache__/
24 | /src/v5_2/__pycache__/
25 | /src/v5_3/__pycache__/
26 | /contrib/devportal/redocly/src/__pycache__/
27 | /contrib/app-protect/src/__pycache__/
28 | /venv/
29 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | The following is a set of guidelines for contributing to NGINX Declarative API. We really appreciate that you are considering contributing!
4 |
5 | ## Getting Started
6 |
7 | Follow our [Getting Started Guide](README.md) to get NGINX Declarative API up and running.
8 |
9 | ## Contributing
10 |
11 | ### Report a Bug
12 |
13 | To report a bug, open an issue on GitHub with the label `bug` using the available bug report issue template. Please ensure the bug has not already been reported.
14 |
15 | ### Suggest a Feature or Enhancement
16 |
17 | To suggest a feature or enhancement, please create an issue on GitHub with the label `enhancement`. Please ensure the feature or enhancement has not already been suggested.
18 |
19 | ### Open a Pull Request
20 |
21 | - Fork the repo, create a branch, implement your changes, add any relevant tests, submit a PR when your changes are **tested** and ready for review.
22 |
23 | ## Code Guidelines
24 |
25 | ### Git Guidelines
26 |
27 | - Keep a clean, concise and meaningful git commit history on your branch (within reason), rebasing locally and squashing before submitting a PR.
28 | - If possible and/or relevant, use the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) format when writing a commit message, so that changelogs can be automatically generated
29 | - Follow the guidelines of writing a good commit message as described here and summarised in the next few points:
30 | - In the subject line, use the present tense ("Add feature" not "Added feature").
31 | - In the subject line, use the imperative mood ("Move cursor to..." not "Moves cursor to...").
32 | - Limit the subject line to 72 characters or less.
33 | - Reference issues and pull requests liberally after the subject line.
34 | - Add more detailed description in the body of the git message (`git commit -a` to give you more space and time in your text editor to write a good message instead of `git commit -am`).
35 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine:latest
2 |
3 | RUN apk update && apk upgrade && \
4 | apk add --update --no-cache python3
5 |
6 | WORKDIR /deployment
7 |
8 | COPY etc/ etc/
9 | COPY src/ src/
10 | COPY templates/ templates/
11 |
12 | RUN python3 -m venv /deployment/env/ && \
13 | source /deployment/env/bin/activate && \
14 | # python3 -m pip install --upgrade pip && \
15 | pip3 install --no-cache --upgrade pip setuptools virtualenv && \
16 | pip3 install -r src/requirements.txt
17 |
18 | WORKDIR /deployment/src
19 | CMD ["/deployment/env/bin/python3", "./main.py"]
20 |
--------------------------------------------------------------------------------
/USAGE-v5.1.md:
--------------------------------------------------------------------------------
1 | # Usage for NGINX Declarative API v5.1
2 |
3 | Version 5.1 supports:
4 |
5 | - [NGINX Instance Manager](https://docs.nginx.com/nginx-management-suite/nim/) 2.14+
6 | - [NGINX One Cloud Console](https://docs.nginx.com/nginx-one/)
7 | - [NGINX Plus](https://docs.nginx.com/nginx/) R30, R31, R32
8 | - [NGINX App Protect WAF](https://docs.nginx.com/nginx-app-protect-waf/) 4 with precompiled [policy bundles](https://docs.nginx.com/nginx-app-protect-waf/v5/admin-guide/compiler/)
9 |
10 | The JSON schema is self explanatory. See also the [sample Postman collection](/contrib/postman) for usage examples
11 |
12 | - `.output.type` defines how NGINX configuration will be returned:
13 | - *nms* - NGINX configuration is published as a Staged Config to NGINX Instance Manager
14 | - `.output.nms.url` the NGINX Instance Manager URL
15 | - `.output.nms.username` the NGINX Instance Manager authentication username
16 | - `.output.nms.password` the NGINX Instance Manager authentication password
17 | - `.output.nms.instancegroup` the NGINX Instance Manager instance group to publish the configuration to
18 | - `.output.nms.synctime` **optional**, used for GitOps autosync. When specified and the declaration includes HTTP(S) references to NGINX App Protect policies, TLS certificates/keys/chains, the HTTP(S) endpoints will be checked every `synctime` seconds and if external contents have changed, the updated configuration will automatically be published to NGINX Instance Manager
19 | - `.output.nms.modules` an optional array of NGINX module names (ie. 'ngx_http_app_protect_module', 'ngx_http_js_module','ngx_stream_js_module')
20 | - `.output.nms.certificates` an optional array of TLS certificates/keys/chains to be published
21 | - `.output.nms.certificates[].type` the item type ('certificate', 'key', 'chain')
22 | - `.output.nms.certificates[].name` the certificate/key/chain name with no path/extension (ie. 'test-application')
23 | - `.output.nms.certificates[].contents` the content: this can be either base64-encoded or be a HTTP(S) URL that will be fetched dynamically from a source of truth
24 | - `.output.nms.policies[]` an optional array of NGINX App Protect security policies
25 | - `.output.nms.policies[].type` the policy type ('app_protect')
26 | - `.output.nms.policies[].name` the policy name (ie. 'prod-policy')
27 | - `.output.nms.policies[].active_tag` the policy tag to enable among all available versions (ie. 'v1')
28 | - `.output.nms.policies[].versions[]` array with all available policy versions
29 | - `.output.nms.policies[].versions[].tag` the policy version's tag name
30 | - `.output.nms.policies[].versions[].displayName` the policy version's display name
31 | - `.output.nms.policies[].versions[].description` the policy version's description
32 | - `.output.nms.policies[].versions[].contents` this can be either base64-encoded or be a HTTP(S) URL that will be fetched dynamically from a source of truth
33 | - *nginxone* - NGINX configuration is published to a NGINX One Cloud Console config sync group
34 | - `.output.nginxone.url` the NGINX One Cloud Console URL
35 | - `.output.nginxone.namespace` the NGINX One Cloud Console namespace
36 | - `.output.nginxone.token` the authentication token
37 | - `.output.nginxone.configsyncgroup` the NGINX One Cloud Console config sync group name
38 | - `.output.nginxone.synctime` **optional**, used for GitOps autosync. When specified and the declaration includes HTTP(S) references to NGINX App Protect policies, TLS certificates/keys/chains, the HTTP(S) endpoints will be checked every `synctime` seconds and if external contents have changed, the updated configuration will automatically be published to NGINX One Cloud Console
39 | - `.output.nginxone.modules` an optional array of NGINX module names (ie. 'ngx_http_app_protect_module', 'ngx_http_js_module','ngx_stream_js_module')
40 | - `.output.nginxone.certificates` an optional array of TLS certificates/keys/chains to be published
41 | - `.output.nginxone.certificates[].type` the item type ('certificate', 'key', 'chain')
42 | - `.output.nginxone.certificates[].name` the certificate/key/chain name with no path/extension (ie. 'test-application')
43 | - `.output.nginxone.certificates[].contents` the content: this can be either base64-encoded or be a HTTP(S) URL that will be fetched dynamically from a source of truth
44 | - `.declaration` describes the NGINX configuration to be created
45 | - `.declaration.http[]` NGINX HTTP definitions
46 | - `.declaration.layer4[]` NGINX TCP/UDP definitions
47 | - `.declaration.resolvers[]` DNS resolvers definitions
48 |
49 | ### API endpoints
50 |
51 | - `POST /v5.1/config/` - Publish a new declaration
52 | - `PATCH /v5.1/config/{config_uid}` - Update an existing declaration
53 | - Per-HTTP server CRUD
54 | - Per-HTTP upstream CRUD
55 | - Per-Stream server CRUD
56 | - Per-Stream upstream CRUD
57 | - Per-NGINX App Protect WAF policy CRUD
58 | - `GET /v5.1/config/{config_uid}` - Retrieve an existing declaration
59 | - `DELETE /v5.1/config/{config_uid}` - Delete an existing declaration
--------------------------------------------------------------------------------
/code_of_conduct.md:
--------------------------------------------------------------------------------
1 |
2 | # Contributor Covenant Code of Conduct
3 |
4 | ## Our Pledge
5 |
6 | We as members, contributors, and leaders pledge to make participation in our
7 | community a harassment-free experience for everyone, regardless of age, body
8 | size, visible or invisible disability, ethnicity, sex characteristics, gender
9 | identity and expression, level of experience, education, socio-economic status,
10 | nationality, personal appearance, race, religion, or sexual identity
11 | and orientation.
12 |
13 | We pledge to act and interact in ways that contribute to an open, welcoming,
14 | diverse, inclusive, and healthy community.
15 |
16 | ## Our Standards
17 |
18 | Examples of behavior that contributes to a positive environment for our
19 | community include:
20 |
21 | * Demonstrating empathy and kindness toward other people
22 | * Being respectful of differing opinions, viewpoints, and experiences
23 | * Giving and gracefully accepting constructive feedback
24 | * Accepting responsibility and apologizing to those affected by our mistakes,
25 | and learning from the experience
26 | * Focusing on what is best not just for us as individuals, but for the
27 | overall community
28 |
29 | Examples of unacceptable behavior include:
30 |
31 | * The use of sexualized language or imagery, and sexual attention or
32 | advances of any kind
33 | * Trolling, insulting or derogatory comments, and personal or political attacks
34 | * Public or private harassment
35 | * Publishing others' private information, such as a physical or email
36 | address, without their explicit permission
37 | * Other conduct which could reasonably be considered inappropriate in a
38 | professional setting
39 |
40 | ## Enforcement Responsibilities
41 |
42 | Community leaders are responsible for clarifying and enforcing our standards of
43 | acceptable behavior and will take appropriate and fair corrective action in
44 | response to any behavior that they deem inappropriate, threatening, offensive,
45 | or harmful.
46 |
47 | Community leaders have the right and responsibility to remove, edit, or reject
48 | comments, commits, code, wiki edits, issues, and other contributions that are
49 | not aligned to this Code of Conduct, and will communicate reasons for moderation
50 | decisions when appropriate.
51 |
52 | ## Scope
53 |
54 | This Code of Conduct applies within all community spaces, and also applies when
55 | an individual is officially representing the community in public spaces.
56 | Examples of representing our community include using an official e-mail address,
57 | posting via an official social media account, or acting as an appointed
58 | representative at an online or offline event.
59 |
60 | ## Enforcement
61 |
62 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
63 | reported to the community leaders responsible for enforcement.
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/contrib/README.md:
--------------------------------------------------------------------------------
1 | # NGINX-Declarative-API contribs
2 |
3 | - [Devportal](devportal) - Redocly CLI wrapper
4 | - [Docker compose](docker-compose) - to run NGINX Declarative API using docker compose
5 | - [GitOps examples](gitops-examples) - sample source of truth objects
6 | - [Kubernetes](kubernetes) - to run NGINX Declarative API on Kubernetes
7 | - [Postman](postman) - Sample Postman collection to test and run NGINX Declarative API
8 |
--------------------------------------------------------------------------------
/contrib/app-protect/Dockerfile:
--------------------------------------------------------------------------------
1 | # syntax=docker/dockerfile:1
2 | ARG VERSION_TAG
3 | ARG BASE_IMAGE=private-registry.nginx.com/nap/waf-compiler:${VERSION_TAG}
4 | FROM ${BASE_IMAGE}
5 |
6 | # Installing packages as root
7 | USER root
8 |
9 | ENV DEBIAN_FRONTEND="noninteractive"
10 |
11 | # REST API wrapper
12 | WORKDIR /compiler
13 | COPY src src/
14 | # REST API wrapper
15 |
16 | RUN --mount=type=secret,id=nginx-crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
17 | --mount=type=secret,id=nginx-key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
18 | apt-get update \
19 | && apt-get install -y \
20 | apt-transport-https \
21 | lsb-release \
22 | ca-certificates \
23 | wget \
24 | gnupg2 \
25 | ubuntu-keyring \
26 | && wget -qO - https://cs.nginx.com/static/keys/app-protect-security-updates.key | gpg --dearmor | \
27 | tee /usr/share/keyrings/app-protect-security-updates.gpg >/dev/null \
28 | && printf "deb [signed-by=/usr/share/keyrings/app-protect-security-updates.gpg] \
29 | https://pkgs.nginx.com/app-protect-security-updates/ubuntu `lsb_release -cs` nginx-plus\n" | \
30 | tee /etc/apt/sources.list.d/nginx-app-protect.list \
31 | && wget -P /etc/apt/apt.conf.d https://cs.nginx.com/static/files/90pkgs-nginx \
32 | && apt-get update \
33 | && apt-get install -y \
34 | app-protect-attack-signatures \
35 | app-protect-bot-signatures \
36 | app-protect-threat-campaigns \
37 | # REST API wrapper
38 | && apt-get -y install python3 python3-venv \
39 | && python3 -m venv /compiler/env/ \
40 | && . /compiler/env/bin/activate \
41 | && pip3 install --no-cache --upgrade pip setuptools virtualenv \
42 | && python3 -m pip install --upgrade pip \
43 | && pip3 install -r /compiler/src/requirements.txt \
44 | # REST API wrapper
45 | && apt-get clean \
46 | && rm -rf /var/lib/apt/lists/*
47 |
48 | # non-root default user (UID 101)
49 | USER nginx
50 |
51 | # REST API wrapper
52 | ENTRYPOINT [ "/compiler/src/start.sh" ]
53 | # REST API wrapper
54 |
--------------------------------------------------------------------------------
/contrib/app-protect/README.md:
--------------------------------------------------------------------------------
1 | # REST API for NGINX App Protect WAF Compiler
2 |
3 | This contrib provides a set of REST API to use the NGINX App Protect 5 policy compiler
4 |
5 | ## REST API Endpoints
6 |
7 | - `/v1/compile/policy` - compiles a JSON policy into a bundle
8 | - Method: `POST`
9 | - Payload: `{"global-settings": "", "policy": "", "cookie-protection-seed": ""}`
10 | - `/v1/compile/logprofile` - compiles a log profile JSON into a bundle
11 | - Method: `POST`
12 | - Payload: `{"logprofile": ""}`
13 | - `/v1/bundle/info` - returns details on a compiled bundle
14 | - Method: `POST`
15 | - Payload: `{"bundle": ""}`
16 |
17 | Headers required for all endpoints:
18 |
19 | ```
20 | Content-Type: application/json
21 | ```
--------------------------------------------------------------------------------
/contrib/app-protect/src/requirements.txt:
--------------------------------------------------------------------------------
1 | typing
2 | uvicorn
3 | fastapi
4 | uuid
5 | pyyaml
6 |
--------------------------------------------------------------------------------
/contrib/app-protect/src/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | /compiler/env/bin/python /compiler/src/server.py
4 |
--------------------------------------------------------------------------------
/contrib/devportal/redocly/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM redocly/cli
2 |
3 | WORKDIR /deployment
4 |
5 | COPY src src/
6 |
7 | RUN apk update && \
8 | apk add --update --no-cache bash python3 && \
9 | python3 -m venv /deployment/env/ && \
10 | . /deployment/env/bin/activate && \
11 | pip3 install --no-cache --upgrade pip setuptools virtualenv && \
12 | python3 -m pip install --upgrade pip && \
13 | pip3 install -r /deployment/src/requirements.txt
14 |
15 | ENTRYPOINT [ "/deployment/src/start.sh" ]
16 |
--------------------------------------------------------------------------------
/contrib/devportal/redocly/README.md:
--------------------------------------------------------------------------------
1 | # Developer portal add-on
2 |
3 | This is a wrapper for [Redocly CLI](https://redocly.com/docs/cli/) used by the NGINX declarative API to create and publish developer portals
4 |
5 | To build:
6 |
7 | docker build --no-cache -t .
8 |
9 | To run the pre-built image:
10 |
11 | docker run --rm -d -p 5001:5000 --name devportal fiorucci/nginx-declarative-api-devportal
12 |
13 | To test:
14 |
15 | curl -i -w '\n' 127.0.0.1:5001/v1/devportal -X POST -H "Content-Type: application/json" -d @
16 |
--------------------------------------------------------------------------------
/contrib/devportal/redocly/src/requirements.txt:
--------------------------------------------------------------------------------
1 | typing
2 | uvicorn
3 | fastapi
4 | uuid
5 |
--------------------------------------------------------------------------------
/contrib/devportal/redocly/src/server.py:
--------------------------------------------------------------------------------
1 | import pathlib
2 | import uvicorn
3 | import subprocess
4 | import json
5 | import uuid
6 |
7 | from typing import Any, Dict, AnyStr, List, Union
8 |
9 | from fastapi import FastAPI, Request
10 | from fastapi.responses import PlainTextResponse, Response, JSONResponse
11 |
12 | app = FastAPI(
13 | title="Redocly connector",
14 | version="1.0.0",
15 | contact={"name": "GitHub", "url": "https://github.com/f5devcentral/NGINX-Declarative-API"}
16 | )
17 |
18 | JSONObject = Dict[AnyStr, Any]
19 | JSONArray = List[Any]
20 | JSONStructure = Union[JSONArray, JSONObject]
21 |
22 | @app.post("/v1/devportal", status_code=200, response_class=JSONResponse)
23 | def post_devportal(response: Response, request: JSONStructure = None):
24 | if request:
25 | try:
26 | sessionUUID = uuid.uuid4()
27 | apiSchema = json.dumps(request)
28 | tmpFileBase = f"/tmp/{sessionUUID}"
29 | tmpFileSchema = f"{tmpFileBase}.json"
30 | tmpFileDocs = f"{tmpFileBase}.html"
31 | tmpFile = open(tmpFileSchema,"w")
32 | tmpFile.write(apiSchema)
33 | tmpFile.close()
34 |
35 | output = subprocess.check_output(f"redocly build-docs '{tmpFileSchema}' --output={tmpFileDocs}", shell=True)
36 |
37 | with open(tmpFileDocs, 'r') as file:
38 | devPortal = file.read().replace('\n','')
39 |
40 | return JSONResponse (content={'status': 'success','apischema': f'{apiSchema}','devportal': f'{devPortal}'}, status_code=200)
41 | except subprocess.CalledProcessError as e:
42 | return JSONResponse (content={'status': str(e)}, status_code=400)
43 | finally:
44 | schemaFile = pathlib.Path(tmpFileSchema)
45 | if schemaFile.is_file():
46 | schemaFile.unlink()
47 |
48 | docsFile = pathlib.Path(tmpFileDocs)
49 | if docsFile.is_file():
50 | docsFile.unlink()
51 | else:
52 | return JSONResponse (content={'status': 'invalid body'}, status_code=400)
53 |
54 | if __name__ == '__main__':
55 | uvicorn.run("server:app", host='0.0.0.0', port=5000)
56 |
--------------------------------------------------------------------------------
/contrib/devportal/redocly/src/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # https://redocly.com/docs/cli/commands/build-docs/
4 |
5 | # Disable telemetry collection
6 | # https://github.com/Redocly/redocly-cli/#data-collection
7 | export REDOCLY_TELEMETRY=off
8 |
9 | /deployment/env/bin/python /deployment/src/server.py
10 |
--------------------------------------------------------------------------------
/contrib/docker-compose/README.md:
--------------------------------------------------------------------------------
1 | # Docker compose
2 |
3 | NGINX Declarative API can be deployed using docker compose on a Linux virtual machine.
4 |
5 | Software prerequisites are:
6 |
7 | - [docker-compose v2.20+](https://github.com/docker/compose)
8 | - [jq](https://github.com/jqlang/jq)
9 |
10 | Usage:
11 |
12 | ```
13 | $ git clone https://github.com/f5devcentral/NGINX-Declarative-API
14 | $ cd NGINX-Declarative-API/contrib/docker-compose
15 | $ ./nginx-dapi.sh
16 | NGINX Declarative API - https://github.com/f5devcentral/NGINX-Declarative-API/
17 |
18 | This script is used to deploy/undeploy NGINX Declarative API using docker-compose
19 |
20 | === Usage:
21 |
22 | ./nginx-dapi.sh [options]
23 |
24 | === Options:
25 |
26 | -h - This help
27 | -w - Enable NGINX App Protect WAF compiler
28 | -c [start|stop|build] - Deployment command
29 | -C [file.crt] - Certificate to pull packages from the official NGINX repository (mandatory with -w)
30 | -K [file.key] - Key to pull packages from the official NGINX repository (mandatory with -w)
31 |
32 | === Examples:
33 |
34 | Deploy NGINX Declarative API:
35 | no NGINX App Protect compiler: ./nginx-dapi.sh -c start
36 | with NGINX App Protect compiler: ./nginx-dapi.sh -c start -w
37 |
38 | Remove NGINX Declarative API:
39 | ./nginx-dapi.sh -c stop
40 |
41 | Build docker images:
42 | no NGINX App Protect compiler: ./nginx-dapi.sh -c build
43 | with NGINX App Protect compiler: ./nginx-dapi.sh -c build -w -C /etc/ssl/nginx/nginx-repo.crt -K /etc/ssl/nginx/nginx-repo.key
44 |
45 | ```
46 |
47 | ## Building docker images
48 |
49 | Without NGINX App Protect compiler
50 |
51 | ```
52 | $ ./nginx-dapi.sh -c build
53 | -> Building NGINX Declarative API Docker images
54 | [+] Building 3.6s (24/24) FINISHED
55 | [...]
56 | => => exporting layers
57 | [...]
58 |
59 | $ docker images
60 | REPOSITORY TAG IMAGE ID CREATED SIZE
61 | nginx-declarative-api-devportal latest e1bd3cf9965a 1 minutes ago 669MB
62 | nginx-declarative-api latest 0d76c5a4338b 1 minutes ago 168MB
63 | ```
64 |
65 | With NGINX App Protect compiler
66 |
67 | ```
68 | $ ./nginx-dapi.sh -c build -w -C /etc/ssl/nginx/nginx-repo.crt -K /etc/ssl/nginx/nginx-repo.key
69 | -> Building NGINX Declarative API Docker images
70 | -> Including NGINX App Protect WAF compiler tag 5.2.0
71 | [+] Building 118.6s (36/36) FINISHED
72 | [...]
73 | => => exporting layers
74 | [...]
75 |
76 | $ docker images
77 | REPOSITORY TAG IMAGE ID CREATED SIZE
78 | nginx-declarative-api-nap-compiler latest cbdaa70bba4b 33 seconds ago 691MB
79 | nginx-declarative-api-devportal latest ad136e8dc5fd About a minute ago 669MB
80 | nginx-declarative-api latest 4c9f89903b6d About a minute ago 174MB
81 | ```
82 |
83 | ## How to run
84 |
85 | 1. Start NGINX Declarative API using the provided `nginx-dapi.sh` script
86 | 2. Start Postman using the collection provided [here](/contrib/postman)
87 |
88 | ### Without NGINX App Protect compiler
89 |
90 | Starting:
91 |
92 | ```commandline
93 | $ ./nginx-dapi.sh -c start
94 | -> Deploying NGINX Declarative API
95 | [+] Building 0.0s (0/0)
96 | [+] Running 4/4
97 | ✔ Network nginx-dapi_dapi-network Created
98 | ✔ Container redis Started
99 | ✔ Container devportal Started
100 | ✔ Container nginx-dapi Started
101 | ```
102 |
103 | Stopping:
104 |
105 | ```commandline
106 | $ ./nginx-dapi.sh -c stop
107 | -> Undeploying NGINX Declarative API
108 | [+] Running 4/4
109 | ✔ Container nginx-dapi Removed
110 | ✔ Container devportal Removed
111 | ✔ Container redis Removed
112 | ✔ Network nginx-dapi_dapi-network Removed
113 | ```
114 |
115 |
116 | #### With NGINX App Protect compiler:
117 |
118 | Starting:
119 |
120 | ```commandline
121 | $ ./nginx-dapi.sh -c start -w
122 | -> Deploying NGINX Declarative API
123 | [+] Building 0.0s (0/0)
124 | [+] Running 5/5
125 | ✔ Network nginx-dapi_dapi-network Created
126 | ✔ Container redis Started
127 | ✔ Container nap-compiler Started
128 | ✔ Container devportal Started
129 | ✔ Container nginx-dapi Started
130 | ```
131 |
132 | Stopping:
133 |
134 | ```commandline
135 | $ ./nginx-dapi.sh -c stop -w
136 | -> Undeploying NGINX Declarative API
137 | [+] Running 5/5
138 | ✔ Container nginx-dapi Removed
139 | ✔ Container devportal Removed
140 | ✔ Container nap-compiler Removed
141 | ✔ Container redis Removed
142 | ✔ Network nginx-dapi_dapi-network Removed
143 | ```
144 |
--------------------------------------------------------------------------------
/contrib/docker-compose/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 |
3 | volumes:
4 | redis_data:
5 |
6 | services:
7 | redis:
8 | image: redis
9 | container_name: "redis"
10 | restart: always
11 | ports:
12 | - "6379:6379"
13 | networks:
14 | - dapi-network
15 | volumes:
16 | - redis_data:/data:rw
17 |
18 | devportal:
19 | image: nginx-declarative-api-devportal
20 | build:
21 | context: ../devportal/redocly
22 | dockerfile: Dockerfile
23 | user: "${USERID}:${USERGROUP}"
24 | container_name: "devportal"
25 | restart: always
26 | ports:
27 | - "5001:5000"
28 | networks:
29 | - dapi-network
30 |
31 | nap-compiler:
32 | profiles:
33 | - nap
34 | image: nginx-declarative-api-nap-compiler
35 | build:
36 | context: ../app-protect
37 | dockerfile: Dockerfile
38 | secrets:
39 | - nginx-crt
40 | - nginx-key
41 | args:
42 | VERSION_TAG: "${NAP_COMPILER_TAG}"
43 | container_name: "nap-compiler"
44 | restart: always
45 | ports:
46 | - "5002:5000"
47 | networks:
48 | - dapi-network
49 |
50 | nginx-dapi:
51 | image: nginx-declarative-api
52 | build:
53 | context: ../../
54 | dockerfile: Dockerfile
55 | user: "${USERID}:${USERGROUP}"
56 | container_name: "nginx-dapi"
57 | restart: always
58 | depends_on:
59 | - redis
60 | ports:
61 | - "5000:5000"
62 | networks:
63 | - dapi-network
64 |
65 | networks:
66 | dapi-network:
67 |
68 | secrets:
69 | nginx-crt:
70 | file: ${NGINX_CERT}
71 | nginx-key:
72 | file: ${NGINX_KEY}
73 |
--------------------------------------------------------------------------------
/contrib/docker-compose/nginx-dapi.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #
4 | # Usage
5 | #
6 | usage() {
7 | BANNER="NGINX Declarative API - https://github.com/f5devcentral/NGINX-Declarative-API/\n\n
8 | This script is used to deploy/undeploy NGINX Declarative API using docker-compose\n\n
9 | === Usage:\n\n
10 | $0 [options]\n\n
11 | === Options:\n\n
12 | -h\t\t\t- This help\n
13 | -w \t\t\t- Enable NGINX App Protect WAF compiler\n
14 | -c [start|stop|build]\t- Deployment command\n
15 | -C [file.crt]\t\t- Certificate to pull packages from the official NGINX repository (mandatory with -w)\n
16 | -K [file.key]\t\t- Key to pull packages from the official NGINX repository (mandatory with -w)\n\n
17 | === Examples:\n\n
18 | Deploy NGINX Declarative API:\n
19 | \tno NGINX App Protect compiler:\t\t$0 -c start\n
20 | \twith NGINX App Protect compiler:\t$0 -c start -w\n\n
21 | Remove NGINX Declarative API:\n
22 | \t$0 -c stop\n\n
23 | Build docker images:\n
24 | \tno NGINX App Protect compiler:\t\t$0 -c build\n
25 | \twith NGINX App Protect compiler:\t$0 -c build -w -C /etc/ssl/nginx/nginx-repo.crt -K /etc/ssl/nginx/nginx-repo.key
26 | \n"
27 |
28 | echo -e $BANNER 2>&1
29 | exit 1
30 | }
31 |
32 | #
33 | # NGINX Declarative API deployment
34 | #
35 | nginx_dapi_start() {
36 |
37 | # Docker compose variables
38 | USERNAME=`whoami`
39 | export USERID=`id -u $USERNAME`
40 | export USERGROUP=`id -g $USERNAME`
41 |
42 | echo "-> Deploying NGINX Declarative API"
43 | COMPOSE_HTTP_TIMEOUT=240 docker-compose -p $PROJECT_NAME -f $DOCKER_COMPOSE_YAML $DOCKER_COMPOSE_PROFILE up -d --remove-orphans
44 | }
45 |
46 | #
47 | # NGINX Declarative API removal
48 | #
49 | nginx_dapi_stop() {
50 |
51 | # Docker compose variables
52 | USERNAME=`whoami`
53 | export USERID=`id -u $USERNAME`
54 | export USERGROUP=`id -g $USERNAME`
55 |
56 | echo "-> Undeploying NGINX Declarative API"
57 | #COMPOSE_HTTP_TIMEOUT=240 docker-compose -p $PROJECT_NAME -f $DOCKER_COMPOSE_YAML $DOCKER_COMPOSE_PROFILE down
58 | COMPOSE_HTTP_TIMEOUT=240 docker-compose -p $PROJECT_NAME -f $DOCKER_COMPOSE_YAML --profile nap down
59 | }
60 |
61 | #
62 | # NGINX Declarative API removal
63 | #
64 | nginx_dapi_build() {
65 |
66 | # Docker compose variables
67 | USERNAME=`whoami`
68 | export USERID=`id -u $USERNAME`
69 | export USERGROUP=`id -g $USERNAME`
70 |
71 | echo "-> Building NGINX Declarative API Docker images"
72 | if ([ ! "${NGINX_CERT}" = "unused" ] && [ ! "${NGINX_KEY}" = "unused" ])
73 | then
74 | export NAP_COMPILER_TAG=`curl -s https://private-registry.nginx.com/v2/nap/waf-compiler/tags/list --key $NGINX_KEY --cert $NGINX_CERT | jq -r '.tags|max'`
75 | echo "-> Including NGINX App Protect WAF compiler tag $NAP_COMPILER_TAG"
76 | fi
77 |
78 | COMPOSE_HTTP_TIMEOUT=240 docker-compose -p $PROJECT_NAME -f $DOCKER_COMPOSE_YAML $DOCKER_COMPOSE_PROFILE build
79 | }
80 |
81 | #
82 | # Main
83 | #
84 |
85 | DOCKER_COMPOSE_YAML="docker-compose.yaml"
86 | PROJECT_NAME="nginx-dapi"
87 | export NGINX_CERT="unused"
88 | export NGINX_KEY="unused"
89 | export PROFILE="basic"
90 | export NAP_COMPILER_TAG="unused"
91 | export DOCKER_COMPOSE_PROFILE=""
92 |
93 | while getopts 'hc:C:K:w' OPTION
94 | do
95 | case "$OPTION" in
96 | h)
97 | usage
98 | ;;
99 | c)
100 | ACTION=$OPTARG
101 | ;;
102 | w)
103 | NAP_ENABLED=true
104 | export DOCKER_COMPOSE_PROFILE="--profile nap"
105 | ;;
106 | C)
107 | export NGINX_CERT=$OPTARG
108 | ;;
109 | K)
110 | export NGINX_KEY=$OPTARG
111 | ;;
112 | esac
113 | done
114 |
115 | if [ -z "${ACTION}" ] || [[ ! "${ACTION}" == +(start|stop|build) ]]
116 | then
117 | usage
118 | fi
119 |
120 | if [ "${ACTION}" == "build" ] && [ "${NAP_ENABLED}" == "true" ]
121 | then
122 | if [ "${NGINX_CERT}" == "unused" ] || [ "${NGINX_KEY}" == "unused" ]
123 | then
124 | echo "NGINX certificate and key missing"
125 | exit
126 | fi
127 | fi
128 |
129 | case "$ACTION" in
130 | start)
131 | nginx_dapi_start
132 | ;;
133 | stop)
134 | nginx_dapi_stop
135 | ;;
136 | build)
137 | nginx_dapi_build
138 | ;;
139 | esac
140 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/jkws.json:
--------------------------------------------------------------------------------
1 | {"keys": [{ "k":"ZmFudGFzdGljand0", "kty":"oct", "kid":"0001" }]}
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.1/apigw.nginx.lab.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
32 | O6C6PJA6ITkdA+LLliWy4eU=
33 | -----END CERTIFICATE-----
34 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.1/apigw.nginx.lab.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | 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
51 | abUSsTGHO/UEOSdj+I8g1bIFrBdg
52 | -----END PRIVATE KEY-----
53 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.1/client.cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIFAjCCA+qgAwIBAgIUavuhXA9aKTRebfvcPESft20TAxswDQYJKoZIhvcNAQEL
3 | BQAwVjELMAkGA1UEBhMCSUUxDTALBgNVBAgMBENvcmsxDTALBgNVBAcMBENvcmsx
4 | ETAPBgNVBAoMCEFjbWUgTHRkMRYwFAYDVQQDDA10ZXN0LmFjbWQubGFuMB4XDTI0
5 | MDQxNTE3MDg1M1oXDTI1MDQxNTE3MDg1M1owWDELMAkGA1UEBhMCSUUxDTALBgNV
6 | BAgMBENvcmsxDTALBgNVBAcMBENvcmsxETAPBgNVBAoMCEFjbWUgTHRkMRgwFgYD
7 | VQQDDA9jbGllbnQuYWNtZS5sYWIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
8 | AoICAQDTCi2v/+sO+u2SpQyePK3xgotrEICdbX2cx7LdrtClO6kLS3r2mjqWZmZD
9 | Qi//GHexXKsZzPTD527FLfTDpLHohu2WfyA+C/G7brqyMOGPgyUpB65cvLu8WPM8
10 | OkyqTWfkLdFqvjAFrU9s31RycOpPJPtpYhEiaAvQX9pFxcjS65BlqAB265bygpk6
11 | jlWQ955VS9ffSKSxiA4BAp30uwFnXEkLpdBzr5NAJyrjuxslrFTK8HloFd62wsAC
12 | F6+DffCaM/5hrIcFK0IQaxpiie2ZYJiQf5rLyWzTmq1XuBk2hHAX3oAF6moaruM8
13 | 9RXqBiZ6qVtaOAqD+JQTcibeszD6glhJ+F3EELBNYXDNaKljkAtqUapa+WdGURE8
14 | vos08M+/9IaY7PxkP5pzl8fi/Qi/DIoV/8tQIrtPHc2jI1RFFh/pix1lGirNTA+D
15 | m9TD2JOHSSufvDdFuub1p2qyMnMwqE6IG8jfLH6LcqDaRng/yZUQ0jkMKHV+wX0z
16 | dgTl05UZ6m0ZE5Ge+QQhngcATzgkIjwZRhwRK8Lu6kpoegoGLRHdMSjqEt6CVsnA
17 | aKgHSm2Q8OLKYIvXU7Ti0OC6nNuN4D9JvLFAwO1EESkBQqPy8Fo/3ESYYMEk2zG4
18 | sr4QrxClncjpmC+vDftrnGNyIRov+Ny/swaRvG/rmyfxDaWM/wIDAQABo4HFMIHC
19 | MAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgWgMDMGCWCGSAGG+EIBDQQmFiRP
20 | cGVuU1NMIEdlbmVyYXRlZCBDbGllbnQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFFBb
21 | vimd61zLKvP4SdYDTVnwXtUpMB8GA1UdIwQYMBaAFKcoFDzLVw5Apb30yQ34snLe
22 | GCQVMA4GA1UdDwEB/wQEAwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH
23 | AwQwDQYJKoZIhvcNAQELBQADggEBAJh4roddEFzbpZNdInsRgnmegYR1IisQLQSB
24 | rcrtFqVkKotlsODQpE18HF0lmP8XOHSHjc+XQQybQMwUbgdMnxAdMVhaZ1ziXIgi
25 | bPx08F4aty0IIcXr9ZEVvSwZayDAdq+ok9DjhF40aNbBaAMpv54B/e79CLIfzDJ8
26 | sYil7+OZmiNQ2meCkyPXuwawxSyTg5XVKt8TKJARyi1IydGZFQ12FXRGLMAJ7Zbx
27 | G9OwVok11zzV6DPdqneNDGpPENVgefV24eMIUu+c8gI8XMMF1OUUdw2iDBe8CMSA
28 | ishvh1VaVO4/zs9fkgKWaWz3pAjk7zdmgZRzWEEGGBLzBhBNEA8=
29 | -----END CERTIFICATE-----
30 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.1/client.key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | 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
51 | B/KL9Bv3fuI/BRKyOVeU5Vvy35/yAqU=
52 | -----END PRIVATE KEY-----
53 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.1/nap-policy-xss-allowed.json:
--------------------------------------------------------------------------------
1 | {
2 | "policy": {
3 | "name": "prod-policy",
4 | "template": {
5 | "name": "POLICY_TEMPLATE_NGINX_BASE"
6 | },
7 | "applicationLanguage": "utf-8",
8 | "enforcementMode": "blocking",
9 | "signature-sets": [
10 | {
11 | "name": "All Signatures",
12 | "block": true,
13 | "alarm": true
14 | }
15 | ],
16 | "signatures": [
17 | {
18 | "signatureId": 200001834,
19 | "enabled": false
20 | },
21 | {
22 | "signatureId": 200001475,
23 | "enabled": false
24 | },
25 | {
26 | "signatureId": 200000098,
27 | "enabled": false
28 | },
29 | {
30 | "signatureId": 200001088,
31 | "enabled": false
32 | },
33 | {
34 | "signatureId": 200101609,
35 | "enabled": false
36 | }
37 | ]
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.1/nap-policy-xss-blocked-bot-allowed.json:
--------------------------------------------------------------------------------
1 | {
2 | "policy": {
3 | "name": "prod-policy",
4 | "template": {
5 | "name": "POLICY_TEMPLATE_NGINX_BASE"
6 | },
7 | "applicationLanguage": "utf-8",
8 | "enforcementMode": "blocking",
9 | "signature-sets": [
10 | {
11 | "name": "All Signatures",
12 | "block": true,
13 | "alarm": true
14 | }
15 | ],
16 | "signatures": [
17 | {
18 | "signatureId": 200001834,
19 | "enabled": false
20 | }
21 | ],
22 | "bot-defense": {
23 | "settings": {
24 | "isEnabled": false
25 | }
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.1/nap-policy-xss-blocked.json:
--------------------------------------------------------------------------------
1 | {
2 | "policy": {
3 | "name": "prod-policy",
4 | "template": {
5 | "name": "POLICY_TEMPLATE_NGINX_BASE"
6 | },
7 | "applicationLanguage": "utf-8",
8 | "enforcementMode": "blocking",
9 | "signature-sets": [
10 | {
11 | "name": "All Signatures",
12 | "block": true,
13 | "alarm": true
14 | }
15 | ],
16 | "signatures": [
17 | {
18 | "signatureId": 200001834,
19 | "enabled": false
20 | }
21 | ]
22 | }
23 | }
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.1/testcert.chain:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDRjCCAi6gAwIBAgIUccT8pYiNoy0AQnkrUZrVCXhnm70wDQYJKoZIhvcNAQEL
3 | BQAwSDEiMCAGCSqGSIb3DQEJARYTbXlAZW1haWxhZGRyZXNzLmNvbTEiMCAGA1UE
4 | AwwZd3d3Lm9ubGluZS1ib3V0aXF1ZS5sb2NhbDAeFw0yMzAyMTQxNTA2NDRaFw0z
5 | MzAyMTExNTA2NDRaMEgxIjAgBgkqhkiG9w0BCQEWE215QGVtYWlsYWRkcmVzcy5j
6 | b20xIjAgBgNVBAMMGXd3dy5vbmxpbmUtYm91dGlxdWUubG9jYWwwggEiMA0GCSqG
7 | SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDasqlTnb5WlPHkjiLnjFX27QBm2BgDcA+x
8 | Y37biaMp+I1bTUd57hDM1X+kBeLZc98xe7hc/HaO5+3ywanBRTMVaBUCKBduET/o
9 | N+DdBAj8c64vov9a064sjXwYSeeh8lPqX52R5DYWxpHh2tvSg+a/3wwmIPoScXIu
10 | R1Wq7RY//dsshIHQkxVa9VAPYjLnusQjH9zOzJGZOxQ/OlCdaUrShbraKg6oVHK1
11 | +2h3M2S7RFjXFr8mbpxSgez1w9oN1YI+RM/kLPgI+Kq+YN6MfMhYvQei537569N9
12 | wJ9bl/i34EbM5gDf8BxhJJbo+ypEC9h0H8FmSXbqXcb8gt/dQMfZAgMBAAGjKDAm
13 | MCQGA1UdEQQdMBuCGXd3dy5vbmxpbmUtYm91dGlxdWUubG9jYWwwDQYJKoZIhvcN
14 | AQELBQADggEBAKLCxBakmK43tbf+2pwgbRLYuOvz4A8GCh/EK2F1OKeuw0oIat7M
15 | Nn5SxSgNFj45XswaRsR3/ObLovrYmXzZnV9IPNHIsB0/sBsyqEYMA55hJsb/8HEd
16 | +bWv2UJdcAimhbLMi1bpgSlSCNMn/CWkX09e3IjRrYkZxT50/ahOBBfBshoY+jwe
17 | sA1VDwZ4neXfrTUXJ4ixiTOfna2TpADLNxk6pncr6uiIpJSmLAq9jQwPBNlrpRN3
18 | TCyKKcadGdUPkALXm0+dMn1OHphy7ZQADMxPwxLySuoCK8kcslpGLg18zPXYQkoD
19 | C1KAguWu/VU4EBT39aC5/9askw+zV4XE9hw=
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.1/testcert.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDRjCCAi6gAwIBAgIUccT8pYiNoy0AQnkrUZrVCXhnm70wDQYJKoZIhvcNAQEL
3 | BQAwSDEiMCAGCSqGSIb3DQEJARYTbXlAZW1haWxhZGRyZXNzLmNvbTEiMCAGA1UE
4 | AwwZd3d3Lm9ubGluZS1ib3V0aXF1ZS5sb2NhbDAeFw0yMzAyMTQxNTA2NDRaFw0z
5 | MzAyMTExNTA2NDRaMEgxIjAgBgkqhkiG9w0BCQEWE215QGVtYWlsYWRkcmVzcy5j
6 | b20xIjAgBgNVBAMMGXd3dy5vbmxpbmUtYm91dGlxdWUubG9jYWwwggEiMA0GCSqG
7 | SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDasqlTnb5WlPHkjiLnjFX27QBm2BgDcA+x
8 | Y37biaMp+I1bTUd57hDM1X+kBeLZc98xe7hc/HaO5+3ywanBRTMVaBUCKBduET/o
9 | N+DdBAj8c64vov9a064sjXwYSeeh8lPqX52R5DYWxpHh2tvSg+a/3wwmIPoScXIu
10 | R1Wq7RY//dsshIHQkxVa9VAPYjLnusQjH9zOzJGZOxQ/OlCdaUrShbraKg6oVHK1
11 | +2h3M2S7RFjXFr8mbpxSgez1w9oN1YI+RM/kLPgI+Kq+YN6MfMhYvQei537569N9
12 | wJ9bl/i34EbM5gDf8BxhJJbo+ypEC9h0H8FmSXbqXcb8gt/dQMfZAgMBAAGjKDAm
13 | MCQGA1UdEQQdMBuCGXd3dy5vbmxpbmUtYm91dGlxdWUubG9jYWwwDQYJKoZIhvcN
14 | AQELBQADggEBAKLCxBakmK43tbf+2pwgbRLYuOvz4A8GCh/EK2F1OKeuw0oIat7M
15 | Nn5SxSgNFj45XswaRsR3/ObLovrYmXzZnV9IPNHIsB0/sBsyqEYMA55hJsb/8HEd
16 | +bWv2UJdcAimhbLMi1bpgSlSCNMn/CWkX09e3IjRrYkZxT50/ahOBBfBshoY+jwe
17 | sA1VDwZ4neXfrTUXJ4ixiTOfna2TpADLNxk6pncr6uiIpJSmLAq9jQwPBNlrpRN3
18 | TCyKKcadGdUPkALXm0+dMn1OHphy7ZQADMxPwxLySuoCK8kcslpGLg18zPXYQkoD
19 | C1KAguWu/VU4EBT39aC5/9askw+zV4XE9hw=
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.1/testcert.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDasqlTnb5WlPHk
3 | jiLnjFX27QBm2BgDcA+xY37biaMp+I1bTUd57hDM1X+kBeLZc98xe7hc/HaO5+3y
4 | wanBRTMVaBUCKBduET/oN+DdBAj8c64vov9a064sjXwYSeeh8lPqX52R5DYWxpHh
5 | 2tvSg+a/3wwmIPoScXIuR1Wq7RY//dsshIHQkxVa9VAPYjLnusQjH9zOzJGZOxQ/
6 | OlCdaUrShbraKg6oVHK1+2h3M2S7RFjXFr8mbpxSgez1w9oN1YI+RM/kLPgI+Kq+
7 | YN6MfMhYvQei537569N9wJ9bl/i34EbM5gDf8BxhJJbo+ypEC9h0H8FmSXbqXcb8
8 | gt/dQMfZAgMBAAECggEBAIcP85baQqSCE+mNBm1ts+FteOQK7LmiyW5J/hxjIktX
9 | XyVV0qCwr9twtwV7RR/6eYq7155FpIqZHdDgXZAoxmWgA+lzDRVCve8SI2MbjNks
10 | MBTnW0CinlyRfGQbsFvJpp2GM2/YOrdSJuIPIdce8rDodT5O+2HMgjGmiHepOCaH
11 | 4XS42Av9KDbcbo2rSfAhSulsXJetd9G7luD3dY3Lsp2TC6ihzwZOtGSHJjoY29uS
12 | D+MJvAq2MzZxRnyE6vP88NY45rZug1YS7EHs0v6NAnI6/Ew6M3sAjss+qhBL/k6j
13 | AMWAibn1oTgbN6ifXapXpynQOSU1IvEJqXNHA+YQMEkCgYEA/t7TihpRoJRcMzx6
14 | 4XtKMMDS/ixv7QUmOnJ1AO1Je3hjJK+2U1wARYLHoVdlZYTb9GRRlH6UHPL3lh2m
15 | ZWfDHRjKzQ+E4jlYFvQMAmAhbSqCAPtyFadQf7qLDKZAT/1WUj+Ynh0vjUUigqKj
16 | VsukDJkwqSt3jCk2ECtddcTicCcCgYEA26rLSaDx/+bDYVlJW9nXt8/N2ZYqtBev
17 | I+AV1qgVYjlskbcMch3apIVELiOEVfBaIGJDoq1N3e25cTvNNO/mA2rDSYLQuz7L
18 | bwlVs6ix02/tFd1R0N5nGKMhziue1l3BOjADHzf/UkOc4UIJGkmUQHrVxpby6FMY
19 | cT+HJ3+OB/8CgYAHtDqWuRbwkKt8zP415KEoehumnTdA5d/y8lTBE2seNVRh3oHX
20 | YTeM4lggc2DYQbzYVVP19iGKAnojaoAGHq3SKlau/iIZKHyWLQhT5g38m8VUPEWF
21 | jAot4jijyD63bEP4tn1pgh5W2dkiM8JWNE+gJd1Hr82sSe6dbIIlti7WDwKBgA3n
22 | PX6nhSmhPXSH5jC+FP05VdoTuxgy947ZvAgeE1xoLgr6/vqqERCgrrQM429dCxdJ
23 | oOZG+cq2JSqZkl9rX6+PrlSUxwlS7CVW/emlH7w2NVdQ7sC9kuDoUlduQ1tmC7jX
24 | GRt8u9hFF0TanSDgz1VVcPpky3MQ71cboj5JwH+ZAoGAAcDSlHuOu2xnbdnaTdE1
25 | MK0q/Yt3EOCGp0FRBkResPhhoV/TXadk0sJJbWFnleRFDkmgsw2QAwVhKQHCRWOu
26 | b4G8EnEXY/91IoRSevWtZTNf+/9+y5w4iOWI3rGJNpXCEgzN7Yc60z1sIsC/fu+Q
27 | YxXNiLIYUB4Pk4pDNRNLMZo=
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.1/testcert2.chain:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDSTCCAjGgAwIBAgIUbzaZNPdYel80IQ81PCNfMllLnYgwDQYJKoZIhvcNAQEL
3 | BQAwSTEiMCAGCSqGSIb3DQEJARYTbXlAZW1haWxhZGRyZXNzLmNvbTEjMCEGA1UE
4 | Awwad3d3Mi5vbmxpbmUtYm91dGlxdWUubG9jYWwwHhcNMjMwMjE0MTUwNzMxWhcN
5 | MzMwMjExMTUwNzMxWjBJMSIwIAYJKoZIhvcNAQkBFhNteUBlbWFpbGFkZHJlc3Mu
6 | Y29tMSMwIQYDVQQDDBp3d3cyLm9ubGluZS1ib3V0aXF1ZS5sb2NhbDCCASIwDQYJ
7 | KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2OHfrfxO6hhg4dGMi0Q4+iwuuNGv2J
8 | eh+t8g9A+dGB4zUkU0SEa2EFLjyAw2P7F1XAtiClHmS9nA0uTuj9nuw9Xk+wFUlm
9 | ahMkdkLBRNNsH3O1gTYUQSOK7xm8FOMBnOYQqJOHILXsXgM2z8QHpX//wl15aGXf
10 | 9vPm4CQUqqsEGNWDfpOQ8jfhrA4T8W1WuAXzJAQmZfhW1qMWxoj1iTCk+Q6nH/8a
11 | MWLWPjTes0bTSRXRTpuQCyeHCaqS8oPPshcd52/FXChnYbNAG1s9Q+35MrgDztL6
12 | dPkNiA9UaUY7pumNip93ZnsYwDmOPnDBPqfvy9Dk1zQuaAsJ1FXwRNsCAwEAAaMp
13 | MCcwJQYDVR0RBB4wHIIad3d3Mi5vbmxpbmUtYm91dGlxdWUubG9jYWwwDQYJKoZI
14 | hvcNAQELBQADggEBADT2SchC4VhWqCYRsw/3nqrVh0JQmD+/x9JjiNsY6fLnG6uW
15 | 8bs8/714qoghJff67H60B6NbrS3lpTZ3bmyotcGtwNNsY4QSFHRu/x4OyIrTfjKb
16 | VIdhRM2Atwc1s1YA6c+2JBquBDhniqABKG9u+j1aa2ElXSalCj+Kozm8ma0yduVw
17 | TX8zS6XZl57vSk/Qo/PZvbmbs8EMOwTUCLn6WQldAARCLughjd9LI9prNpBlYon6
18 | jmZ8oi59arK16cKe6i6tQ3QExT2kQsLlrK/jFw0xqrFnveKgUTeevViT4WZnqsCm
19 | awrPhrbDn0F7HmFSrgenrW8BIuJ2crBHy0230Lc=
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.1/testcert2.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDSTCCAjGgAwIBAgIUbzaZNPdYel80IQ81PCNfMllLnYgwDQYJKoZIhvcNAQEL
3 | BQAwSTEiMCAGCSqGSIb3DQEJARYTbXlAZW1haWxhZGRyZXNzLmNvbTEjMCEGA1UE
4 | Awwad3d3Mi5vbmxpbmUtYm91dGlxdWUubG9jYWwwHhcNMjMwMjE0MTUwNzMxWhcN
5 | MzMwMjExMTUwNzMxWjBJMSIwIAYJKoZIhvcNAQkBFhNteUBlbWFpbGFkZHJlc3Mu
6 | Y29tMSMwIQYDVQQDDBp3d3cyLm9ubGluZS1ib3V0aXF1ZS5sb2NhbDCCASIwDQYJ
7 | KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2OHfrfxO6hhg4dGMi0Q4+iwuuNGv2J
8 | eh+t8g9A+dGB4zUkU0SEa2EFLjyAw2P7F1XAtiClHmS9nA0uTuj9nuw9Xk+wFUlm
9 | ahMkdkLBRNNsH3O1gTYUQSOK7xm8FOMBnOYQqJOHILXsXgM2z8QHpX//wl15aGXf
10 | 9vPm4CQUqqsEGNWDfpOQ8jfhrA4T8W1WuAXzJAQmZfhW1qMWxoj1iTCk+Q6nH/8a
11 | MWLWPjTes0bTSRXRTpuQCyeHCaqS8oPPshcd52/FXChnYbNAG1s9Q+35MrgDztL6
12 | dPkNiA9UaUY7pumNip93ZnsYwDmOPnDBPqfvy9Dk1zQuaAsJ1FXwRNsCAwEAAaMp
13 | MCcwJQYDVR0RBB4wHIIad3d3Mi5vbmxpbmUtYm91dGlxdWUubG9jYWwwDQYJKoZI
14 | hvcNAQELBQADggEBADT2SchC4VhWqCYRsw/3nqrVh0JQmD+/x9JjiNsY6fLnG6uW
15 | 8bs8/714qoghJff67H60B6NbrS3lpTZ3bmyotcGtwNNsY4QSFHRu/x4OyIrTfjKb
16 | VIdhRM2Atwc1s1YA6c+2JBquBDhniqABKG9u+j1aa2ElXSalCj+Kozm8ma0yduVw
17 | TX8zS6XZl57vSk/Qo/PZvbmbs8EMOwTUCLn6WQldAARCLughjd9LI9prNpBlYon6
18 | jmZ8oi59arK16cKe6i6tQ3QExT2kQsLlrK/jFw0xqrFnveKgUTeevViT4WZnqsCm
19 | awrPhrbDn0F7HmFSrgenrW8BIuJ2crBHy0230Lc=
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.1/testcert2.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDdjh3638TuoYYO
3 | HRjItEOPosLrjRr9iXofrfIPQPnRgeM1JFNEhGthBS48gMNj+xdVwLYgpR5kvZwN
4 | Lk7o/Z7sPV5PsBVJZmoTJHZCwUTTbB9ztYE2FEEjiu8ZvBTjAZzmEKiThyC17F4D
5 | Ns/EB6V//8JdeWhl3/bz5uAkFKqrBBjVg36TkPI34awOE/FtVrgF8yQEJmX4Vtaj
6 | FsaI9YkwpPkOpx//GjFi1j403rNG00kV0U6bkAsnhwmqkvKDz7IXHedvxVwoZ2Gz
7 | QBtbPUPt+TK4A87S+nT5DYgPVGlGO6bpjYqfd2Z7GMA5jj5wwT6n78vQ5Nc0LmgL
8 | CdRV8ETbAgMBAAECggEBAJkAy010eWC+5YAbsgDxFHM+WNQo90m+RjtYegD0w1Ff
9 | HNSXSHXZ6PnwhPS9i7IhNgU/d8dloG67zuf/YflfJQBKhTYNCTZOZtTfalhBdlF3
10 | quTSpO/+3tk32lVwYRBADeWH/ZMcT4ezO12G3can7TBPJSA+ds1b9QSNHZ9tMku0
11 | 2J2pzT8C8V0vHn49oKO9D4Q+QwRvisT6FKNaOW/xKZjtUIvyjVvjENnBW7MQ5y5z
12 | IHsUNkwGgZ2V2IbDouM4+A42J9iDsseM2euSsaDfum3vj9MPTqXE8zUUdX+/miMq
13 | RJTXLxDdkPaCbQftQ7y/cIAFLDZS8Fvvsa5pX69jl1ECgYEA8sQ6S7kcyYgBLX4T
14 | KVYPg1sFTgCofW5nTgCND4kiVvIDz/uk9vsfuMj7FMS3fcCfZorPdYEKa+Zwi4wZ
15 | NMCSArtezbwFBeaOiZTpjh2k8CBrtumdcU/EfzQOvrVcSzVc27ditwRAmONeBXVw
16 | GSvqSfjQKLDh/4Y191qOmgyIBDMCgYEA6aHjQr43XM811VQhTPBtLlBccD8hCS23
17 | NcujPMa85Vz+RES3OqHt2nH9NGuYrexGbrSt3ckjxnO+TdsS4f94bKhquXvv7AkX
18 | 7qr8KZEwHncyjcL3uTChbjWr2xJR4lSnS5PAbnWfyR48HXkHO9IVPe/IcYnvuGDN
19 | AeMJkCgp1LkCgYEArvD/PXAxMX1js9/FeSU+Wp8t7G8G/BSiNxColkhxSYxveOJT
20 | l3OSAXw7i1TTEbjMZX2kUH3j/6t48ObNhzk6PuO9Rq62Q/FISBbaU4JDSJNka9Rf
21 | k7cy16Ow+HcDAmN6/g5iAZb74fD+4Rom5MzDsfiuMJR+179khlJortRW9AcCgYAD
22 | 4AKD9eG3MVykOCwBOa+l6AFQf0uN+msigkkn1egGKd+xxC4B0/O8/s0DVJGIuPWG
23 | GosTtaVZQkwywGJ0yyb1Lmnuv6aAFLqH4+Ag1F6m8rUs8sHnGW5kBJHgJVKkXWEU
24 | +NNlQaAv1seKeZpsHJTrnRGHCJGoTjq4QErFUFU5SQKBgEYMGdnPP4ZDAeezPCML
25 | 42RVHOAG9IsMl4mV7+fwcEHcmuvb8nNgKNfayjG/NbiQWtT4v7iQH4GHYzUobaqr
26 | 3xnQlec3jBrLEsWR8ItRWKxKO2GGLlbmQ99Kn3UGh+6FtXbxwB0hhkFfKXJzM10N
27 | Y9ruUdyYpjGO/j9ROjoBepUH
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.2/apigw.nginx.lab.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
32 | O6C6PJA6ITkdA+LLliWy4eU=
33 | -----END CERTIFICATE-----
34 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.2/apigw.nginx.lab.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | 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
51 | abUSsTGHO/UEOSdj+I8g1bIFrBdg
52 | -----END PRIVATE KEY-----
53 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.2/client.cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIFAjCCA+qgAwIBAgIUavuhXA9aKTRebfvcPESft20TAxswDQYJKoZIhvcNAQEL
3 | BQAwVjELMAkGA1UEBhMCSUUxDTALBgNVBAgMBENvcmsxDTALBgNVBAcMBENvcmsx
4 | ETAPBgNVBAoMCEFjbWUgTHRkMRYwFAYDVQQDDA10ZXN0LmFjbWQubGFuMB4XDTI0
5 | MDQxNTE3MDg1M1oXDTI1MDQxNTE3MDg1M1owWDELMAkGA1UEBhMCSUUxDTALBgNV
6 | BAgMBENvcmsxDTALBgNVBAcMBENvcmsxETAPBgNVBAoMCEFjbWUgTHRkMRgwFgYD
7 | VQQDDA9jbGllbnQuYWNtZS5sYWIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
8 | AoICAQDTCi2v/+sO+u2SpQyePK3xgotrEICdbX2cx7LdrtClO6kLS3r2mjqWZmZD
9 | Qi//GHexXKsZzPTD527FLfTDpLHohu2WfyA+C/G7brqyMOGPgyUpB65cvLu8WPM8
10 | OkyqTWfkLdFqvjAFrU9s31RycOpPJPtpYhEiaAvQX9pFxcjS65BlqAB265bygpk6
11 | jlWQ955VS9ffSKSxiA4BAp30uwFnXEkLpdBzr5NAJyrjuxslrFTK8HloFd62wsAC
12 | F6+DffCaM/5hrIcFK0IQaxpiie2ZYJiQf5rLyWzTmq1XuBk2hHAX3oAF6moaruM8
13 | 9RXqBiZ6qVtaOAqD+JQTcibeszD6glhJ+F3EELBNYXDNaKljkAtqUapa+WdGURE8
14 | vos08M+/9IaY7PxkP5pzl8fi/Qi/DIoV/8tQIrtPHc2jI1RFFh/pix1lGirNTA+D
15 | m9TD2JOHSSufvDdFuub1p2qyMnMwqE6IG8jfLH6LcqDaRng/yZUQ0jkMKHV+wX0z
16 | dgTl05UZ6m0ZE5Ge+QQhngcATzgkIjwZRhwRK8Lu6kpoegoGLRHdMSjqEt6CVsnA
17 | aKgHSm2Q8OLKYIvXU7Ti0OC6nNuN4D9JvLFAwO1EESkBQqPy8Fo/3ESYYMEk2zG4
18 | sr4QrxClncjpmC+vDftrnGNyIRov+Ny/swaRvG/rmyfxDaWM/wIDAQABo4HFMIHC
19 | MAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgWgMDMGCWCGSAGG+EIBDQQmFiRP
20 | cGVuU1NMIEdlbmVyYXRlZCBDbGllbnQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFFBb
21 | vimd61zLKvP4SdYDTVnwXtUpMB8GA1UdIwQYMBaAFKcoFDzLVw5Apb30yQ34snLe
22 | GCQVMA4GA1UdDwEB/wQEAwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH
23 | AwQwDQYJKoZIhvcNAQELBQADggEBAJh4roddEFzbpZNdInsRgnmegYR1IisQLQSB
24 | rcrtFqVkKotlsODQpE18HF0lmP8XOHSHjc+XQQybQMwUbgdMnxAdMVhaZ1ziXIgi
25 | bPx08F4aty0IIcXr9ZEVvSwZayDAdq+ok9DjhF40aNbBaAMpv54B/e79CLIfzDJ8
26 | sYil7+OZmiNQ2meCkyPXuwawxSyTg5XVKt8TKJARyi1IydGZFQ12FXRGLMAJ7Zbx
27 | G9OwVok11zzV6DPdqneNDGpPENVgefV24eMIUu+c8gI8XMMF1OUUdw2iDBe8CMSA
28 | ishvh1VaVO4/zs9fkgKWaWz3pAjk7zdmgZRzWEEGGBLzBhBNEA8=
29 | -----END CERTIFICATE-----
30 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.2/client.key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | 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
51 | B/KL9Bv3fuI/BRKyOVeU5Vvy35/yAqU=
52 | -----END PRIVATE KEY-----
53 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.2/nap-policy-xss-allowed.json:
--------------------------------------------------------------------------------
1 | {
2 | "policy": {
3 | "name": "prod-policy",
4 | "template": {
5 | "name": "POLICY_TEMPLATE_NGINX_BASE"
6 | },
7 | "applicationLanguage": "utf-8",
8 | "enforcementMode": "blocking",
9 | "signature-sets": [
10 | {
11 | "name": "All Signatures",
12 | "block": true,
13 | "alarm": true
14 | }
15 | ],
16 | "signatures": [
17 | {
18 | "signatureId": 200001834,
19 | "enabled": false
20 | },
21 | {
22 | "signatureId": 200001475,
23 | "enabled": false
24 | },
25 | {
26 | "signatureId": 200000098,
27 | "enabled": false
28 | },
29 | {
30 | "signatureId": 200001088,
31 | "enabled": false
32 | },
33 | {
34 | "signatureId": 200101609,
35 | "enabled": false
36 | }
37 | ]
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.2/nap-policy-xss-blocked-bot-allowed.json:
--------------------------------------------------------------------------------
1 | {
2 | "policy": {
3 | "name": "prod-policy",
4 | "template": {
5 | "name": "POLICY_TEMPLATE_NGINX_BASE"
6 | },
7 | "applicationLanguage": "utf-8",
8 | "enforcementMode": "blocking",
9 | "signature-sets": [
10 | {
11 | "name": "All Signatures",
12 | "block": true,
13 | "alarm": true
14 | }
15 | ],
16 | "signatures": [
17 | {
18 | "signatureId": 200001834,
19 | "enabled": false
20 | }
21 | ],
22 | "bot-defense": {
23 | "settings": {
24 | "isEnabled": false
25 | }
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.2/nap-policy-xss-blocked.json:
--------------------------------------------------------------------------------
1 | {
2 | "policy": {
3 | "name": "prod-policy",
4 | "template": {
5 | "name": "POLICY_TEMPLATE_NGINX_BASE"
6 | },
7 | "applicationLanguage": "utf-8",
8 | "enforcementMode": "blocking",
9 | "signature-sets": [
10 | {
11 | "name": "All Signatures",
12 | "block": true,
13 | "alarm": true
14 | }
15 | ],
16 | "signatures": [
17 | {
18 | "signatureId": 200001834,
19 | "enabled": false
20 | }
21 | ]
22 | }
23 | }
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.2/testcert.chain:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDRjCCAi6gAwIBAgIUccT8pYiNoy0AQnkrUZrVCXhnm70wDQYJKoZIhvcNAQEL
3 | BQAwSDEiMCAGCSqGSIb3DQEJARYTbXlAZW1haWxhZGRyZXNzLmNvbTEiMCAGA1UE
4 | AwwZd3d3Lm9ubGluZS1ib3V0aXF1ZS5sb2NhbDAeFw0yMzAyMTQxNTA2NDRaFw0z
5 | MzAyMTExNTA2NDRaMEgxIjAgBgkqhkiG9w0BCQEWE215QGVtYWlsYWRkcmVzcy5j
6 | b20xIjAgBgNVBAMMGXd3dy5vbmxpbmUtYm91dGlxdWUubG9jYWwwggEiMA0GCSqG
7 | SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDasqlTnb5WlPHkjiLnjFX27QBm2BgDcA+x
8 | Y37biaMp+I1bTUd57hDM1X+kBeLZc98xe7hc/HaO5+3ywanBRTMVaBUCKBduET/o
9 | N+DdBAj8c64vov9a064sjXwYSeeh8lPqX52R5DYWxpHh2tvSg+a/3wwmIPoScXIu
10 | R1Wq7RY//dsshIHQkxVa9VAPYjLnusQjH9zOzJGZOxQ/OlCdaUrShbraKg6oVHK1
11 | +2h3M2S7RFjXFr8mbpxSgez1w9oN1YI+RM/kLPgI+Kq+YN6MfMhYvQei537569N9
12 | wJ9bl/i34EbM5gDf8BxhJJbo+ypEC9h0H8FmSXbqXcb8gt/dQMfZAgMBAAGjKDAm
13 | MCQGA1UdEQQdMBuCGXd3dy5vbmxpbmUtYm91dGlxdWUubG9jYWwwDQYJKoZIhvcN
14 | AQELBQADggEBAKLCxBakmK43tbf+2pwgbRLYuOvz4A8GCh/EK2F1OKeuw0oIat7M
15 | Nn5SxSgNFj45XswaRsR3/ObLovrYmXzZnV9IPNHIsB0/sBsyqEYMA55hJsb/8HEd
16 | +bWv2UJdcAimhbLMi1bpgSlSCNMn/CWkX09e3IjRrYkZxT50/ahOBBfBshoY+jwe
17 | sA1VDwZ4neXfrTUXJ4ixiTOfna2TpADLNxk6pncr6uiIpJSmLAq9jQwPBNlrpRN3
18 | TCyKKcadGdUPkALXm0+dMn1OHphy7ZQADMxPwxLySuoCK8kcslpGLg18zPXYQkoD
19 | C1KAguWu/VU4EBT39aC5/9askw+zV4XE9hw=
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.2/testcert.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDRjCCAi6gAwIBAgIUccT8pYiNoy0AQnkrUZrVCXhnm70wDQYJKoZIhvcNAQEL
3 | BQAwSDEiMCAGCSqGSIb3DQEJARYTbXlAZW1haWxhZGRyZXNzLmNvbTEiMCAGA1UE
4 | AwwZd3d3Lm9ubGluZS1ib3V0aXF1ZS5sb2NhbDAeFw0yMzAyMTQxNTA2NDRaFw0z
5 | MzAyMTExNTA2NDRaMEgxIjAgBgkqhkiG9w0BCQEWE215QGVtYWlsYWRkcmVzcy5j
6 | b20xIjAgBgNVBAMMGXd3dy5vbmxpbmUtYm91dGlxdWUubG9jYWwwggEiMA0GCSqG
7 | SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDasqlTnb5WlPHkjiLnjFX27QBm2BgDcA+x
8 | Y37biaMp+I1bTUd57hDM1X+kBeLZc98xe7hc/HaO5+3ywanBRTMVaBUCKBduET/o
9 | N+DdBAj8c64vov9a064sjXwYSeeh8lPqX52R5DYWxpHh2tvSg+a/3wwmIPoScXIu
10 | R1Wq7RY//dsshIHQkxVa9VAPYjLnusQjH9zOzJGZOxQ/OlCdaUrShbraKg6oVHK1
11 | +2h3M2S7RFjXFr8mbpxSgez1w9oN1YI+RM/kLPgI+Kq+YN6MfMhYvQei537569N9
12 | wJ9bl/i34EbM5gDf8BxhJJbo+ypEC9h0H8FmSXbqXcb8gt/dQMfZAgMBAAGjKDAm
13 | MCQGA1UdEQQdMBuCGXd3dy5vbmxpbmUtYm91dGlxdWUubG9jYWwwDQYJKoZIhvcN
14 | AQELBQADggEBAKLCxBakmK43tbf+2pwgbRLYuOvz4A8GCh/EK2F1OKeuw0oIat7M
15 | Nn5SxSgNFj45XswaRsR3/ObLovrYmXzZnV9IPNHIsB0/sBsyqEYMA55hJsb/8HEd
16 | +bWv2UJdcAimhbLMi1bpgSlSCNMn/CWkX09e3IjRrYkZxT50/ahOBBfBshoY+jwe
17 | sA1VDwZ4neXfrTUXJ4ixiTOfna2TpADLNxk6pncr6uiIpJSmLAq9jQwPBNlrpRN3
18 | TCyKKcadGdUPkALXm0+dMn1OHphy7ZQADMxPwxLySuoCK8kcslpGLg18zPXYQkoD
19 | C1KAguWu/VU4EBT39aC5/9askw+zV4XE9hw=
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.2/testcert.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDasqlTnb5WlPHk
3 | jiLnjFX27QBm2BgDcA+xY37biaMp+I1bTUd57hDM1X+kBeLZc98xe7hc/HaO5+3y
4 | wanBRTMVaBUCKBduET/oN+DdBAj8c64vov9a064sjXwYSeeh8lPqX52R5DYWxpHh
5 | 2tvSg+a/3wwmIPoScXIuR1Wq7RY//dsshIHQkxVa9VAPYjLnusQjH9zOzJGZOxQ/
6 | OlCdaUrShbraKg6oVHK1+2h3M2S7RFjXFr8mbpxSgez1w9oN1YI+RM/kLPgI+Kq+
7 | YN6MfMhYvQei537569N9wJ9bl/i34EbM5gDf8BxhJJbo+ypEC9h0H8FmSXbqXcb8
8 | gt/dQMfZAgMBAAECggEBAIcP85baQqSCE+mNBm1ts+FteOQK7LmiyW5J/hxjIktX
9 | XyVV0qCwr9twtwV7RR/6eYq7155FpIqZHdDgXZAoxmWgA+lzDRVCve8SI2MbjNks
10 | MBTnW0CinlyRfGQbsFvJpp2GM2/YOrdSJuIPIdce8rDodT5O+2HMgjGmiHepOCaH
11 | 4XS42Av9KDbcbo2rSfAhSulsXJetd9G7luD3dY3Lsp2TC6ihzwZOtGSHJjoY29uS
12 | D+MJvAq2MzZxRnyE6vP88NY45rZug1YS7EHs0v6NAnI6/Ew6M3sAjss+qhBL/k6j
13 | AMWAibn1oTgbN6ifXapXpynQOSU1IvEJqXNHA+YQMEkCgYEA/t7TihpRoJRcMzx6
14 | 4XtKMMDS/ixv7QUmOnJ1AO1Je3hjJK+2U1wARYLHoVdlZYTb9GRRlH6UHPL3lh2m
15 | ZWfDHRjKzQ+E4jlYFvQMAmAhbSqCAPtyFadQf7qLDKZAT/1WUj+Ynh0vjUUigqKj
16 | VsukDJkwqSt3jCk2ECtddcTicCcCgYEA26rLSaDx/+bDYVlJW9nXt8/N2ZYqtBev
17 | I+AV1qgVYjlskbcMch3apIVELiOEVfBaIGJDoq1N3e25cTvNNO/mA2rDSYLQuz7L
18 | bwlVs6ix02/tFd1R0N5nGKMhziue1l3BOjADHzf/UkOc4UIJGkmUQHrVxpby6FMY
19 | cT+HJ3+OB/8CgYAHtDqWuRbwkKt8zP415KEoehumnTdA5d/y8lTBE2seNVRh3oHX
20 | YTeM4lggc2DYQbzYVVP19iGKAnojaoAGHq3SKlau/iIZKHyWLQhT5g38m8VUPEWF
21 | jAot4jijyD63bEP4tn1pgh5W2dkiM8JWNE+gJd1Hr82sSe6dbIIlti7WDwKBgA3n
22 | PX6nhSmhPXSH5jC+FP05VdoTuxgy947ZvAgeE1xoLgr6/vqqERCgrrQM429dCxdJ
23 | oOZG+cq2JSqZkl9rX6+PrlSUxwlS7CVW/emlH7w2NVdQ7sC9kuDoUlduQ1tmC7jX
24 | GRt8u9hFF0TanSDgz1VVcPpky3MQ71cboj5JwH+ZAoGAAcDSlHuOu2xnbdnaTdE1
25 | MK0q/Yt3EOCGp0FRBkResPhhoV/TXadk0sJJbWFnleRFDkmgsw2QAwVhKQHCRWOu
26 | b4G8EnEXY/91IoRSevWtZTNf+/9+y5w4iOWI3rGJNpXCEgzN7Yc60z1sIsC/fu+Q
27 | YxXNiLIYUB4Pk4pDNRNLMZo=
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.2/testcert2.chain:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDSTCCAjGgAwIBAgIUbzaZNPdYel80IQ81PCNfMllLnYgwDQYJKoZIhvcNAQEL
3 | BQAwSTEiMCAGCSqGSIb3DQEJARYTbXlAZW1haWxhZGRyZXNzLmNvbTEjMCEGA1UE
4 | Awwad3d3Mi5vbmxpbmUtYm91dGlxdWUubG9jYWwwHhcNMjMwMjE0MTUwNzMxWhcN
5 | MzMwMjExMTUwNzMxWjBJMSIwIAYJKoZIhvcNAQkBFhNteUBlbWFpbGFkZHJlc3Mu
6 | Y29tMSMwIQYDVQQDDBp3d3cyLm9ubGluZS1ib3V0aXF1ZS5sb2NhbDCCASIwDQYJ
7 | KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2OHfrfxO6hhg4dGMi0Q4+iwuuNGv2J
8 | eh+t8g9A+dGB4zUkU0SEa2EFLjyAw2P7F1XAtiClHmS9nA0uTuj9nuw9Xk+wFUlm
9 | ahMkdkLBRNNsH3O1gTYUQSOK7xm8FOMBnOYQqJOHILXsXgM2z8QHpX//wl15aGXf
10 | 9vPm4CQUqqsEGNWDfpOQ8jfhrA4T8W1WuAXzJAQmZfhW1qMWxoj1iTCk+Q6nH/8a
11 | MWLWPjTes0bTSRXRTpuQCyeHCaqS8oPPshcd52/FXChnYbNAG1s9Q+35MrgDztL6
12 | dPkNiA9UaUY7pumNip93ZnsYwDmOPnDBPqfvy9Dk1zQuaAsJ1FXwRNsCAwEAAaMp
13 | MCcwJQYDVR0RBB4wHIIad3d3Mi5vbmxpbmUtYm91dGlxdWUubG9jYWwwDQYJKoZI
14 | hvcNAQELBQADggEBADT2SchC4VhWqCYRsw/3nqrVh0JQmD+/x9JjiNsY6fLnG6uW
15 | 8bs8/714qoghJff67H60B6NbrS3lpTZ3bmyotcGtwNNsY4QSFHRu/x4OyIrTfjKb
16 | VIdhRM2Atwc1s1YA6c+2JBquBDhniqABKG9u+j1aa2ElXSalCj+Kozm8ma0yduVw
17 | TX8zS6XZl57vSk/Qo/PZvbmbs8EMOwTUCLn6WQldAARCLughjd9LI9prNpBlYon6
18 | jmZ8oi59arK16cKe6i6tQ3QExT2kQsLlrK/jFw0xqrFnveKgUTeevViT4WZnqsCm
19 | awrPhrbDn0F7HmFSrgenrW8BIuJ2crBHy0230Lc=
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.2/testcert2.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDSTCCAjGgAwIBAgIUbzaZNPdYel80IQ81PCNfMllLnYgwDQYJKoZIhvcNAQEL
3 | BQAwSTEiMCAGCSqGSIb3DQEJARYTbXlAZW1haWxhZGRyZXNzLmNvbTEjMCEGA1UE
4 | Awwad3d3Mi5vbmxpbmUtYm91dGlxdWUubG9jYWwwHhcNMjMwMjE0MTUwNzMxWhcN
5 | MzMwMjExMTUwNzMxWjBJMSIwIAYJKoZIhvcNAQkBFhNteUBlbWFpbGFkZHJlc3Mu
6 | Y29tMSMwIQYDVQQDDBp3d3cyLm9ubGluZS1ib3V0aXF1ZS5sb2NhbDCCASIwDQYJ
7 | KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2OHfrfxO6hhg4dGMi0Q4+iwuuNGv2J
8 | eh+t8g9A+dGB4zUkU0SEa2EFLjyAw2P7F1XAtiClHmS9nA0uTuj9nuw9Xk+wFUlm
9 | ahMkdkLBRNNsH3O1gTYUQSOK7xm8FOMBnOYQqJOHILXsXgM2z8QHpX//wl15aGXf
10 | 9vPm4CQUqqsEGNWDfpOQ8jfhrA4T8W1WuAXzJAQmZfhW1qMWxoj1iTCk+Q6nH/8a
11 | MWLWPjTes0bTSRXRTpuQCyeHCaqS8oPPshcd52/FXChnYbNAG1s9Q+35MrgDztL6
12 | dPkNiA9UaUY7pumNip93ZnsYwDmOPnDBPqfvy9Dk1zQuaAsJ1FXwRNsCAwEAAaMp
13 | MCcwJQYDVR0RBB4wHIIad3d3Mi5vbmxpbmUtYm91dGlxdWUubG9jYWwwDQYJKoZI
14 | hvcNAQELBQADggEBADT2SchC4VhWqCYRsw/3nqrVh0JQmD+/x9JjiNsY6fLnG6uW
15 | 8bs8/714qoghJff67H60B6NbrS3lpTZ3bmyotcGtwNNsY4QSFHRu/x4OyIrTfjKb
16 | VIdhRM2Atwc1s1YA6c+2JBquBDhniqABKG9u+j1aa2ElXSalCj+Kozm8ma0yduVw
17 | TX8zS6XZl57vSk/Qo/PZvbmbs8EMOwTUCLn6WQldAARCLughjd9LI9prNpBlYon6
18 | jmZ8oi59arK16cKe6i6tQ3QExT2kQsLlrK/jFw0xqrFnveKgUTeevViT4WZnqsCm
19 | awrPhrbDn0F7HmFSrgenrW8BIuJ2crBHy0230Lc=
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.2/testcert2.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDdjh3638TuoYYO
3 | HRjItEOPosLrjRr9iXofrfIPQPnRgeM1JFNEhGthBS48gMNj+xdVwLYgpR5kvZwN
4 | Lk7o/Z7sPV5PsBVJZmoTJHZCwUTTbB9ztYE2FEEjiu8ZvBTjAZzmEKiThyC17F4D
5 | Ns/EB6V//8JdeWhl3/bz5uAkFKqrBBjVg36TkPI34awOE/FtVrgF8yQEJmX4Vtaj
6 | FsaI9YkwpPkOpx//GjFi1j403rNG00kV0U6bkAsnhwmqkvKDz7IXHedvxVwoZ2Gz
7 | QBtbPUPt+TK4A87S+nT5DYgPVGlGO6bpjYqfd2Z7GMA5jj5wwT6n78vQ5Nc0LmgL
8 | CdRV8ETbAgMBAAECggEBAJkAy010eWC+5YAbsgDxFHM+WNQo90m+RjtYegD0w1Ff
9 | HNSXSHXZ6PnwhPS9i7IhNgU/d8dloG67zuf/YflfJQBKhTYNCTZOZtTfalhBdlF3
10 | quTSpO/+3tk32lVwYRBADeWH/ZMcT4ezO12G3can7TBPJSA+ds1b9QSNHZ9tMku0
11 | 2J2pzT8C8V0vHn49oKO9D4Q+QwRvisT6FKNaOW/xKZjtUIvyjVvjENnBW7MQ5y5z
12 | IHsUNkwGgZ2V2IbDouM4+A42J9iDsseM2euSsaDfum3vj9MPTqXE8zUUdX+/miMq
13 | RJTXLxDdkPaCbQftQ7y/cIAFLDZS8Fvvsa5pX69jl1ECgYEA8sQ6S7kcyYgBLX4T
14 | KVYPg1sFTgCofW5nTgCND4kiVvIDz/uk9vsfuMj7FMS3fcCfZorPdYEKa+Zwi4wZ
15 | NMCSArtezbwFBeaOiZTpjh2k8CBrtumdcU/EfzQOvrVcSzVc27ditwRAmONeBXVw
16 | GSvqSfjQKLDh/4Y191qOmgyIBDMCgYEA6aHjQr43XM811VQhTPBtLlBccD8hCS23
17 | NcujPMa85Vz+RES3OqHt2nH9NGuYrexGbrSt3ckjxnO+TdsS4f94bKhquXvv7AkX
18 | 7qr8KZEwHncyjcL3uTChbjWr2xJR4lSnS5PAbnWfyR48HXkHO9IVPe/IcYnvuGDN
19 | AeMJkCgp1LkCgYEArvD/PXAxMX1js9/FeSU+Wp8t7G8G/BSiNxColkhxSYxveOJT
20 | l3OSAXw7i1TTEbjMZX2kUH3j/6t48ObNhzk6PuO9Rq62Q/FISBbaU4JDSJNka9Rf
21 | k7cy16Ow+HcDAmN6/g5iAZb74fD+4Rom5MzDsfiuMJR+179khlJortRW9AcCgYAD
22 | 4AKD9eG3MVykOCwBOa+l6AFQf0uN+msigkkn1egGKd+xxC4B0/O8/s0DVJGIuPWG
23 | GosTtaVZQkwywGJ0yyb1Lmnuv6aAFLqH4+Ag1F6m8rUs8sHnGW5kBJHgJVKkXWEU
24 | +NNlQaAv1seKeZpsHJTrnRGHCJGoTjq4QErFUFU5SQKBgEYMGdnPP4ZDAeezPCML
25 | 42RVHOAG9IsMl4mV7+fwcEHcmuvb8nNgKNfayjG/NbiQWtT4v7iQH4GHYzUobaqr
26 | 3xnQlec3jBrLEsWR8ItRWKxKO2GGLlbmQ99Kn3UGh+6FtXbxwB0hhkFfKXJzM10N
27 | Y9ruUdyYpjGO/j9ROjoBepUH
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.3/apigw.nginx.lab.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
32 | O6C6PJA6ITkdA+LLliWy4eU=
33 | -----END CERTIFICATE-----
34 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.3/apigw.nginx.lab.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | 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
51 | abUSsTGHO/UEOSdj+I8g1bIFrBdg
52 | -----END PRIVATE KEY-----
53 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.3/client.cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIFAjCCA+qgAwIBAgIUavuhXA9aKTRebfvcPESft20TAxswDQYJKoZIhvcNAQEL
3 | BQAwVjELMAkGA1UEBhMCSUUxDTALBgNVBAgMBENvcmsxDTALBgNVBAcMBENvcmsx
4 | ETAPBgNVBAoMCEFjbWUgTHRkMRYwFAYDVQQDDA10ZXN0LmFjbWQubGFuMB4XDTI0
5 | MDQxNTE3MDg1M1oXDTI1MDQxNTE3MDg1M1owWDELMAkGA1UEBhMCSUUxDTALBgNV
6 | BAgMBENvcmsxDTALBgNVBAcMBENvcmsxETAPBgNVBAoMCEFjbWUgTHRkMRgwFgYD
7 | VQQDDA9jbGllbnQuYWNtZS5sYWIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
8 | AoICAQDTCi2v/+sO+u2SpQyePK3xgotrEICdbX2cx7LdrtClO6kLS3r2mjqWZmZD
9 | Qi//GHexXKsZzPTD527FLfTDpLHohu2WfyA+C/G7brqyMOGPgyUpB65cvLu8WPM8
10 | OkyqTWfkLdFqvjAFrU9s31RycOpPJPtpYhEiaAvQX9pFxcjS65BlqAB265bygpk6
11 | jlWQ955VS9ffSKSxiA4BAp30uwFnXEkLpdBzr5NAJyrjuxslrFTK8HloFd62wsAC
12 | F6+DffCaM/5hrIcFK0IQaxpiie2ZYJiQf5rLyWzTmq1XuBk2hHAX3oAF6moaruM8
13 | 9RXqBiZ6qVtaOAqD+JQTcibeszD6glhJ+F3EELBNYXDNaKljkAtqUapa+WdGURE8
14 | vos08M+/9IaY7PxkP5pzl8fi/Qi/DIoV/8tQIrtPHc2jI1RFFh/pix1lGirNTA+D
15 | m9TD2JOHSSufvDdFuub1p2qyMnMwqE6IG8jfLH6LcqDaRng/yZUQ0jkMKHV+wX0z
16 | dgTl05UZ6m0ZE5Ge+QQhngcATzgkIjwZRhwRK8Lu6kpoegoGLRHdMSjqEt6CVsnA
17 | aKgHSm2Q8OLKYIvXU7Ti0OC6nNuN4D9JvLFAwO1EESkBQqPy8Fo/3ESYYMEk2zG4
18 | sr4QrxClncjpmC+vDftrnGNyIRov+Ny/swaRvG/rmyfxDaWM/wIDAQABo4HFMIHC
19 | MAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgWgMDMGCWCGSAGG+EIBDQQmFiRP
20 | cGVuU1NMIEdlbmVyYXRlZCBDbGllbnQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFFBb
21 | vimd61zLKvP4SdYDTVnwXtUpMB8GA1UdIwQYMBaAFKcoFDzLVw5Apb30yQ34snLe
22 | GCQVMA4GA1UdDwEB/wQEAwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH
23 | AwQwDQYJKoZIhvcNAQELBQADggEBAJh4roddEFzbpZNdInsRgnmegYR1IisQLQSB
24 | rcrtFqVkKotlsODQpE18HF0lmP8XOHSHjc+XQQybQMwUbgdMnxAdMVhaZ1ziXIgi
25 | bPx08F4aty0IIcXr9ZEVvSwZayDAdq+ok9DjhF40aNbBaAMpv54B/e79CLIfzDJ8
26 | sYil7+OZmiNQ2meCkyPXuwawxSyTg5XVKt8TKJARyi1IydGZFQ12FXRGLMAJ7Zbx
27 | G9OwVok11zzV6DPdqneNDGpPENVgefV24eMIUu+c8gI8XMMF1OUUdw2iDBe8CMSA
28 | ishvh1VaVO4/zs9fkgKWaWz3pAjk7zdmgZRzWEEGGBLzBhBNEA8=
29 | -----END CERTIFICATE-----
30 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.3/client.key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | 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
51 | B/KL9Bv3fuI/BRKyOVeU5Vvy35/yAqU=
52 | -----END PRIVATE KEY-----
53 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.3/nap-policy-xss-allowed.json:
--------------------------------------------------------------------------------
1 | {
2 | "policy": {
3 | "name": "prod-policy",
4 | "template": {
5 | "name": "POLICY_TEMPLATE_NGINX_BASE"
6 | },
7 | "applicationLanguage": "utf-8",
8 | "enforcementMode": "blocking",
9 | "signature-sets": [
10 | {
11 | "name": "All Signatures",
12 | "block": true,
13 | "alarm": true
14 | }
15 | ],
16 | "signatures": [
17 | {
18 | "signatureId": 200001834,
19 | "enabled": false
20 | },
21 | {
22 | "signatureId": 200001475,
23 | "enabled": false
24 | },
25 | {
26 | "signatureId": 200000098,
27 | "enabled": false
28 | },
29 | {
30 | "signatureId": 200001088,
31 | "enabled": false
32 | },
33 | {
34 | "signatureId": 200101609,
35 | "enabled": false
36 | }
37 | ]
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.3/nap-policy-xss-blocked-bot-allowed.json:
--------------------------------------------------------------------------------
1 | {
2 | "policy": {
3 | "name": "prod-policy",
4 | "template": {
5 | "name": "POLICY_TEMPLATE_NGINX_BASE"
6 | },
7 | "applicationLanguage": "utf-8",
8 | "enforcementMode": "blocking",
9 | "signature-sets": [
10 | {
11 | "name": "All Signatures",
12 | "block": true,
13 | "alarm": true
14 | }
15 | ],
16 | "signatures": [
17 | {
18 | "signatureId": 200001834,
19 | "enabled": false
20 | }
21 | ],
22 | "bot-defense": {
23 | "settings": {
24 | "isEnabled": false
25 | }
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.3/nap-policy-xss-blocked.json:
--------------------------------------------------------------------------------
1 | {
2 | "policy": {
3 | "name": "prod-policy",
4 | "template": {
5 | "name": "POLICY_TEMPLATE_NGINX_BASE"
6 | },
7 | "applicationLanguage": "utf-8",
8 | "enforcementMode": "blocking",
9 | "signature-sets": [
10 | {
11 | "name": "All Signatures",
12 | "block": true,
13 | "alarm": true
14 | }
15 | ],
16 | "signatures": [
17 | {
18 | "signatureId": 200001834,
19 | "enabled": false
20 | }
21 | ]
22 | }
23 | }
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.3/testcert.chain:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDRjCCAi6gAwIBAgIUccT8pYiNoy0AQnkrUZrVCXhnm70wDQYJKoZIhvcNAQEL
3 | BQAwSDEiMCAGCSqGSIb3DQEJARYTbXlAZW1haWxhZGRyZXNzLmNvbTEiMCAGA1UE
4 | AwwZd3d3Lm9ubGluZS1ib3V0aXF1ZS5sb2NhbDAeFw0yMzAyMTQxNTA2NDRaFw0z
5 | MzAyMTExNTA2NDRaMEgxIjAgBgkqhkiG9w0BCQEWE215QGVtYWlsYWRkcmVzcy5j
6 | b20xIjAgBgNVBAMMGXd3dy5vbmxpbmUtYm91dGlxdWUubG9jYWwwggEiMA0GCSqG
7 | SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDasqlTnb5WlPHkjiLnjFX27QBm2BgDcA+x
8 | Y37biaMp+I1bTUd57hDM1X+kBeLZc98xe7hc/HaO5+3ywanBRTMVaBUCKBduET/o
9 | N+DdBAj8c64vov9a064sjXwYSeeh8lPqX52R5DYWxpHh2tvSg+a/3wwmIPoScXIu
10 | R1Wq7RY//dsshIHQkxVa9VAPYjLnusQjH9zOzJGZOxQ/OlCdaUrShbraKg6oVHK1
11 | +2h3M2S7RFjXFr8mbpxSgez1w9oN1YI+RM/kLPgI+Kq+YN6MfMhYvQei537569N9
12 | wJ9bl/i34EbM5gDf8BxhJJbo+ypEC9h0H8FmSXbqXcb8gt/dQMfZAgMBAAGjKDAm
13 | MCQGA1UdEQQdMBuCGXd3dy5vbmxpbmUtYm91dGlxdWUubG9jYWwwDQYJKoZIhvcN
14 | AQELBQADggEBAKLCxBakmK43tbf+2pwgbRLYuOvz4A8GCh/EK2F1OKeuw0oIat7M
15 | Nn5SxSgNFj45XswaRsR3/ObLovrYmXzZnV9IPNHIsB0/sBsyqEYMA55hJsb/8HEd
16 | +bWv2UJdcAimhbLMi1bpgSlSCNMn/CWkX09e3IjRrYkZxT50/ahOBBfBshoY+jwe
17 | sA1VDwZ4neXfrTUXJ4ixiTOfna2TpADLNxk6pncr6uiIpJSmLAq9jQwPBNlrpRN3
18 | TCyKKcadGdUPkALXm0+dMn1OHphy7ZQADMxPwxLySuoCK8kcslpGLg18zPXYQkoD
19 | C1KAguWu/VU4EBT39aC5/9askw+zV4XE9hw=
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.3/testcert.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDRjCCAi6gAwIBAgIUccT8pYiNoy0AQnkrUZrVCXhnm70wDQYJKoZIhvcNAQEL
3 | BQAwSDEiMCAGCSqGSIb3DQEJARYTbXlAZW1haWxhZGRyZXNzLmNvbTEiMCAGA1UE
4 | AwwZd3d3Lm9ubGluZS1ib3V0aXF1ZS5sb2NhbDAeFw0yMzAyMTQxNTA2NDRaFw0z
5 | MzAyMTExNTA2NDRaMEgxIjAgBgkqhkiG9w0BCQEWE215QGVtYWlsYWRkcmVzcy5j
6 | b20xIjAgBgNVBAMMGXd3dy5vbmxpbmUtYm91dGlxdWUubG9jYWwwggEiMA0GCSqG
7 | SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDasqlTnb5WlPHkjiLnjFX27QBm2BgDcA+x
8 | Y37biaMp+I1bTUd57hDM1X+kBeLZc98xe7hc/HaO5+3ywanBRTMVaBUCKBduET/o
9 | N+DdBAj8c64vov9a064sjXwYSeeh8lPqX52R5DYWxpHh2tvSg+a/3wwmIPoScXIu
10 | R1Wq7RY//dsshIHQkxVa9VAPYjLnusQjH9zOzJGZOxQ/OlCdaUrShbraKg6oVHK1
11 | +2h3M2S7RFjXFr8mbpxSgez1w9oN1YI+RM/kLPgI+Kq+YN6MfMhYvQei537569N9
12 | wJ9bl/i34EbM5gDf8BxhJJbo+ypEC9h0H8FmSXbqXcb8gt/dQMfZAgMBAAGjKDAm
13 | MCQGA1UdEQQdMBuCGXd3dy5vbmxpbmUtYm91dGlxdWUubG9jYWwwDQYJKoZIhvcN
14 | AQELBQADggEBAKLCxBakmK43tbf+2pwgbRLYuOvz4A8GCh/EK2F1OKeuw0oIat7M
15 | Nn5SxSgNFj45XswaRsR3/ObLovrYmXzZnV9IPNHIsB0/sBsyqEYMA55hJsb/8HEd
16 | +bWv2UJdcAimhbLMi1bpgSlSCNMn/CWkX09e3IjRrYkZxT50/ahOBBfBshoY+jwe
17 | sA1VDwZ4neXfrTUXJ4ixiTOfna2TpADLNxk6pncr6uiIpJSmLAq9jQwPBNlrpRN3
18 | TCyKKcadGdUPkALXm0+dMn1OHphy7ZQADMxPwxLySuoCK8kcslpGLg18zPXYQkoD
19 | C1KAguWu/VU4EBT39aC5/9askw+zV4XE9hw=
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.3/testcert.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDasqlTnb5WlPHk
3 | jiLnjFX27QBm2BgDcA+xY37biaMp+I1bTUd57hDM1X+kBeLZc98xe7hc/HaO5+3y
4 | wanBRTMVaBUCKBduET/oN+DdBAj8c64vov9a064sjXwYSeeh8lPqX52R5DYWxpHh
5 | 2tvSg+a/3wwmIPoScXIuR1Wq7RY//dsshIHQkxVa9VAPYjLnusQjH9zOzJGZOxQ/
6 | OlCdaUrShbraKg6oVHK1+2h3M2S7RFjXFr8mbpxSgez1w9oN1YI+RM/kLPgI+Kq+
7 | YN6MfMhYvQei537569N9wJ9bl/i34EbM5gDf8BxhJJbo+ypEC9h0H8FmSXbqXcb8
8 | gt/dQMfZAgMBAAECggEBAIcP85baQqSCE+mNBm1ts+FteOQK7LmiyW5J/hxjIktX
9 | XyVV0qCwr9twtwV7RR/6eYq7155FpIqZHdDgXZAoxmWgA+lzDRVCve8SI2MbjNks
10 | MBTnW0CinlyRfGQbsFvJpp2GM2/YOrdSJuIPIdce8rDodT5O+2HMgjGmiHepOCaH
11 | 4XS42Av9KDbcbo2rSfAhSulsXJetd9G7luD3dY3Lsp2TC6ihzwZOtGSHJjoY29uS
12 | D+MJvAq2MzZxRnyE6vP88NY45rZug1YS7EHs0v6NAnI6/Ew6M3sAjss+qhBL/k6j
13 | AMWAibn1oTgbN6ifXapXpynQOSU1IvEJqXNHA+YQMEkCgYEA/t7TihpRoJRcMzx6
14 | 4XtKMMDS/ixv7QUmOnJ1AO1Je3hjJK+2U1wARYLHoVdlZYTb9GRRlH6UHPL3lh2m
15 | ZWfDHRjKzQ+E4jlYFvQMAmAhbSqCAPtyFadQf7qLDKZAT/1WUj+Ynh0vjUUigqKj
16 | VsukDJkwqSt3jCk2ECtddcTicCcCgYEA26rLSaDx/+bDYVlJW9nXt8/N2ZYqtBev
17 | I+AV1qgVYjlskbcMch3apIVELiOEVfBaIGJDoq1N3e25cTvNNO/mA2rDSYLQuz7L
18 | bwlVs6ix02/tFd1R0N5nGKMhziue1l3BOjADHzf/UkOc4UIJGkmUQHrVxpby6FMY
19 | cT+HJ3+OB/8CgYAHtDqWuRbwkKt8zP415KEoehumnTdA5d/y8lTBE2seNVRh3oHX
20 | YTeM4lggc2DYQbzYVVP19iGKAnojaoAGHq3SKlau/iIZKHyWLQhT5g38m8VUPEWF
21 | jAot4jijyD63bEP4tn1pgh5W2dkiM8JWNE+gJd1Hr82sSe6dbIIlti7WDwKBgA3n
22 | PX6nhSmhPXSH5jC+FP05VdoTuxgy947ZvAgeE1xoLgr6/vqqERCgrrQM429dCxdJ
23 | oOZG+cq2JSqZkl9rX6+PrlSUxwlS7CVW/emlH7w2NVdQ7sC9kuDoUlduQ1tmC7jX
24 | GRt8u9hFF0TanSDgz1VVcPpky3MQ71cboj5JwH+ZAoGAAcDSlHuOu2xnbdnaTdE1
25 | MK0q/Yt3EOCGp0FRBkResPhhoV/TXadk0sJJbWFnleRFDkmgsw2QAwVhKQHCRWOu
26 | b4G8EnEXY/91IoRSevWtZTNf+/9+y5w4iOWI3rGJNpXCEgzN7Yc60z1sIsC/fu+Q
27 | YxXNiLIYUB4Pk4pDNRNLMZo=
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.3/testcert2.chain:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDSTCCAjGgAwIBAgIUbzaZNPdYel80IQ81PCNfMllLnYgwDQYJKoZIhvcNAQEL
3 | BQAwSTEiMCAGCSqGSIb3DQEJARYTbXlAZW1haWxhZGRyZXNzLmNvbTEjMCEGA1UE
4 | Awwad3d3Mi5vbmxpbmUtYm91dGlxdWUubG9jYWwwHhcNMjMwMjE0MTUwNzMxWhcN
5 | MzMwMjExMTUwNzMxWjBJMSIwIAYJKoZIhvcNAQkBFhNteUBlbWFpbGFkZHJlc3Mu
6 | Y29tMSMwIQYDVQQDDBp3d3cyLm9ubGluZS1ib3V0aXF1ZS5sb2NhbDCCASIwDQYJ
7 | KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2OHfrfxO6hhg4dGMi0Q4+iwuuNGv2J
8 | eh+t8g9A+dGB4zUkU0SEa2EFLjyAw2P7F1XAtiClHmS9nA0uTuj9nuw9Xk+wFUlm
9 | ahMkdkLBRNNsH3O1gTYUQSOK7xm8FOMBnOYQqJOHILXsXgM2z8QHpX//wl15aGXf
10 | 9vPm4CQUqqsEGNWDfpOQ8jfhrA4T8W1WuAXzJAQmZfhW1qMWxoj1iTCk+Q6nH/8a
11 | MWLWPjTes0bTSRXRTpuQCyeHCaqS8oPPshcd52/FXChnYbNAG1s9Q+35MrgDztL6
12 | dPkNiA9UaUY7pumNip93ZnsYwDmOPnDBPqfvy9Dk1zQuaAsJ1FXwRNsCAwEAAaMp
13 | MCcwJQYDVR0RBB4wHIIad3d3Mi5vbmxpbmUtYm91dGlxdWUubG9jYWwwDQYJKoZI
14 | hvcNAQELBQADggEBADT2SchC4VhWqCYRsw/3nqrVh0JQmD+/x9JjiNsY6fLnG6uW
15 | 8bs8/714qoghJff67H60B6NbrS3lpTZ3bmyotcGtwNNsY4QSFHRu/x4OyIrTfjKb
16 | VIdhRM2Atwc1s1YA6c+2JBquBDhniqABKG9u+j1aa2ElXSalCj+Kozm8ma0yduVw
17 | TX8zS6XZl57vSk/Qo/PZvbmbs8EMOwTUCLn6WQldAARCLughjd9LI9prNpBlYon6
18 | jmZ8oi59arK16cKe6i6tQ3QExT2kQsLlrK/jFw0xqrFnveKgUTeevViT4WZnqsCm
19 | awrPhrbDn0F7HmFSrgenrW8BIuJ2crBHy0230Lc=
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.3/testcert2.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDSTCCAjGgAwIBAgIUbzaZNPdYel80IQ81PCNfMllLnYgwDQYJKoZIhvcNAQEL
3 | BQAwSTEiMCAGCSqGSIb3DQEJARYTbXlAZW1haWxhZGRyZXNzLmNvbTEjMCEGA1UE
4 | Awwad3d3Mi5vbmxpbmUtYm91dGlxdWUubG9jYWwwHhcNMjMwMjE0MTUwNzMxWhcN
5 | MzMwMjExMTUwNzMxWjBJMSIwIAYJKoZIhvcNAQkBFhNteUBlbWFpbGFkZHJlc3Mu
6 | Y29tMSMwIQYDVQQDDBp3d3cyLm9ubGluZS1ib3V0aXF1ZS5sb2NhbDCCASIwDQYJ
7 | KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2OHfrfxO6hhg4dGMi0Q4+iwuuNGv2J
8 | eh+t8g9A+dGB4zUkU0SEa2EFLjyAw2P7F1XAtiClHmS9nA0uTuj9nuw9Xk+wFUlm
9 | ahMkdkLBRNNsH3O1gTYUQSOK7xm8FOMBnOYQqJOHILXsXgM2z8QHpX//wl15aGXf
10 | 9vPm4CQUqqsEGNWDfpOQ8jfhrA4T8W1WuAXzJAQmZfhW1qMWxoj1iTCk+Q6nH/8a
11 | MWLWPjTes0bTSRXRTpuQCyeHCaqS8oPPshcd52/FXChnYbNAG1s9Q+35MrgDztL6
12 | dPkNiA9UaUY7pumNip93ZnsYwDmOPnDBPqfvy9Dk1zQuaAsJ1FXwRNsCAwEAAaMp
13 | MCcwJQYDVR0RBB4wHIIad3d3Mi5vbmxpbmUtYm91dGlxdWUubG9jYWwwDQYJKoZI
14 | hvcNAQELBQADggEBADT2SchC4VhWqCYRsw/3nqrVh0JQmD+/x9JjiNsY6fLnG6uW
15 | 8bs8/714qoghJff67H60B6NbrS3lpTZ3bmyotcGtwNNsY4QSFHRu/x4OyIrTfjKb
16 | VIdhRM2Atwc1s1YA6c+2JBquBDhniqABKG9u+j1aa2ElXSalCj+Kozm8ma0yduVw
17 | TX8zS6XZl57vSk/Qo/PZvbmbs8EMOwTUCLn6WQldAARCLughjd9LI9prNpBlYon6
18 | jmZ8oi59arK16cKe6i6tQ3QExT2kQsLlrK/jFw0xqrFnveKgUTeevViT4WZnqsCm
19 | awrPhrbDn0F7HmFSrgenrW8BIuJ2crBHy0230Lc=
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/contrib/gitops-examples/v5.3/testcert2.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDdjh3638TuoYYO
3 | HRjItEOPosLrjRr9iXofrfIPQPnRgeM1JFNEhGthBS48gMNj+xdVwLYgpR5kvZwN
4 | Lk7o/Z7sPV5PsBVJZmoTJHZCwUTTbB9ztYE2FEEjiu8ZvBTjAZzmEKiThyC17F4D
5 | Ns/EB6V//8JdeWhl3/bz5uAkFKqrBBjVg36TkPI34awOE/FtVrgF8yQEJmX4Vtaj
6 | FsaI9YkwpPkOpx//GjFi1j403rNG00kV0U6bkAsnhwmqkvKDz7IXHedvxVwoZ2Gz
7 | QBtbPUPt+TK4A87S+nT5DYgPVGlGO6bpjYqfd2Z7GMA5jj5wwT6n78vQ5Nc0LmgL
8 | CdRV8ETbAgMBAAECggEBAJkAy010eWC+5YAbsgDxFHM+WNQo90m+RjtYegD0w1Ff
9 | HNSXSHXZ6PnwhPS9i7IhNgU/d8dloG67zuf/YflfJQBKhTYNCTZOZtTfalhBdlF3
10 | quTSpO/+3tk32lVwYRBADeWH/ZMcT4ezO12G3can7TBPJSA+ds1b9QSNHZ9tMku0
11 | 2J2pzT8C8V0vHn49oKO9D4Q+QwRvisT6FKNaOW/xKZjtUIvyjVvjENnBW7MQ5y5z
12 | IHsUNkwGgZ2V2IbDouM4+A42J9iDsseM2euSsaDfum3vj9MPTqXE8zUUdX+/miMq
13 | RJTXLxDdkPaCbQftQ7y/cIAFLDZS8Fvvsa5pX69jl1ECgYEA8sQ6S7kcyYgBLX4T
14 | KVYPg1sFTgCofW5nTgCND4kiVvIDz/uk9vsfuMj7FMS3fcCfZorPdYEKa+Zwi4wZ
15 | NMCSArtezbwFBeaOiZTpjh2k8CBrtumdcU/EfzQOvrVcSzVc27ditwRAmONeBXVw
16 | GSvqSfjQKLDh/4Y191qOmgyIBDMCgYEA6aHjQr43XM811VQhTPBtLlBccD8hCS23
17 | NcujPMa85Vz+RES3OqHt2nH9NGuYrexGbrSt3ckjxnO+TdsS4f94bKhquXvv7AkX
18 | 7qr8KZEwHncyjcL3uTChbjWr2xJR4lSnS5PAbnWfyR48HXkHO9IVPe/IcYnvuGDN
19 | AeMJkCgp1LkCgYEArvD/PXAxMX1js9/FeSU+Wp8t7G8G/BSiNxColkhxSYxveOJT
20 | l3OSAXw7i1TTEbjMZX2kUH3j/6t48ObNhzk6PuO9Rq62Q/FISBbaU4JDSJNka9Rf
21 | k7cy16Ow+HcDAmN6/g5iAZb74fD+4Rom5MzDsfiuMJR+179khlJortRW9AcCgYAD
22 | 4AKD9eG3MVykOCwBOa+l6AFQf0uN+msigkkn1egGKd+xxC4B0/O8/s0DVJGIuPWG
23 | GosTtaVZQkwywGJ0yyb1Lmnuv6aAFLqH4+Ag1F6m8rUs8sHnGW5kBJHgJVKkXWEU
24 | +NNlQaAv1seKeZpsHJTrnRGHCJGoTjq4QErFUFU5SQKBgEYMGdnPP4ZDAeezPCML
25 | 42RVHOAG9IsMl4mV7+fwcEHcmuvb8nNgKNfayjG/NbiQWtT4v7iQH4GHYzUobaqr
26 | 3xnQlec3jBrLEsWR8ItRWKxKO2GGLlbmQ99Kn3UGh+6FtXbxwB0hhkFfKXJzM10N
27 | Y9ruUdyYpjGO/j9ROjoBepUH
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/contrib/kubernetes/README.md:
--------------------------------------------------------------------------------
1 | # Running NGINX Declarative API on Kubernetes
2 |
3 | NGINX Declarative API can be deployed on Kubernetes using the manifest provided
4 |
5 | ## How to deploy
6 |
7 | 1. Build the NGINX Declarative API docker images using the [Docker-compose script](/contrib/docker-compose)
8 |
9 | 2. Tag and push the docker images to a private registry
10 |
11 | ```
12 | docker tag nginx-declarative-api:latest YOUR_REGISTRY_HERE/nginx-declarative-api:latest
13 | docker push YOUR_REGISTRY_HERE/nginx-declarative-api:latest
14 |
15 | docker tag nginx-declarative-api-devportal:latest YOUR_REGISTRY_HERE/nginx-declarative-api-devportal:latest
16 | docker push YOUR_REGISTRY_HERE/nginx-declarative-api-devportal:latest
17 | ```
18 |
19 | 3. Edit `nginx-declarative-api.yaml` and update the following lines to match the docker images and to set the `Ingress` host DNS name
20 |
21 | ```
22 | image: YOUR_REGISTRY_HERE/nginx-declarative-api:latest
23 | image: YOUR_REGISTRY_HERE/nginx-declarative-api-devportal:latest
24 | ```
25 |
26 | ```
27 | - host: nginx-dapi.k8s.f5.ff.lan
28 | ```
29 |
30 | 4. Apply the manifest
31 |
32 | ```
33 | $ kubectl apply -f nginx-declarative-api.yaml
34 | namespace/nginx-dapi created
35 | deployment.apps/redis created
36 | deployment.apps/nginx-dapi created
37 | deployment.apps/devportal created
38 | service/redis created
39 | service/nginx-dapi created
40 | service/devportal created
41 | ingress.networking.k8s.io/nginx-dapi created
42 | ```
43 |
44 | 5. Make sure all pods are up and running
45 |
46 | ```
47 | $ kubectl get all -n nginx-dapi
48 | NAME READY STATUS RESTARTS AGE
49 | pod/devportal-74fc5c9ccb-5wjpr 1/1 Running 0 25s
50 | pod/nginx-dapi-848599b79b-ll2kg 1/1 Running 0 25s
51 | pod/redis-5cdb78b899-hjz9x 1/1 Running 0 25s
52 | ```
53 |
54 | 6. The NGINX Declarative API can be accessed through its `Ingress` resource
55 |
56 | ```
57 | $ kubectl get ingress -n nginx-dapi
58 | NAME CLASS HOSTS ADDRESS PORTS AGE
59 | nginx-dapi nginx nginx-dapi.k8s.f5.ff.lan 80 34s
60 | ```
61 |
62 | ## How to undeploy
63 |
64 | 1. Delete the `nginx-declarative-api.yaml` manifest
65 |
66 | ```
67 | kubectl delete -f nginx-declarative-api.yaml
68 | ```
69 |
--------------------------------------------------------------------------------
/contrib/kubernetes/nginx-declarative-api.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: nginx-dapi
5 |
6 | ---
7 | apiVersion: apps/v1
8 | kind: Deployment
9 | metadata:
10 | name: redis
11 | namespace: nginx-dapi
12 | labels:
13 | app: redis
14 | spec:
15 | selector:
16 | matchLabels:
17 | app: redis
18 | replicas: 1
19 | template:
20 | metadata:
21 | labels:
22 | app: redis
23 | spec:
24 | containers:
25 | - name: redis
26 | image: redis
27 | ports:
28 | - name: redis
29 | containerPort: 6379
30 |
31 | ---
32 | apiVersion: apps/v1
33 | kind: Deployment
34 | metadata:
35 | name: nginx-dapi
36 | namespace: nginx-dapi
37 | labels:
38 | app: nginx-dapi
39 | spec:
40 | selector:
41 | matchLabels:
42 | app: nginx-dapi
43 | replicas: 1
44 | template:
45 | metadata:
46 | labels:
47 | app: nginx-dapi
48 | spec:
49 | containers:
50 | - name: nginx-dapi
51 | image: YOUR_REGISTRY_HERE/nginx-declarative-api:latest
52 | ports:
53 | - name: http
54 | containerPort: 5000
55 |
56 | ---
57 | apiVersion: apps/v1
58 | kind: Deployment
59 | metadata:
60 | name: devportal
61 | namespace: nginx-dapi
62 | labels:
63 | app: devportal
64 | spec:
65 | selector:
66 | matchLabels:
67 | app: devportal
68 | replicas: 1
69 | template:
70 | metadata:
71 | labels:
72 | app: devportal
73 | spec:
74 | containers:
75 | - name: devportal
76 | image: YOUR_REGISTRY_HERE/nginx-declarative-api-devportal:latest
77 | ports:
78 | - name: http
79 | containerPort: 5000
80 |
81 | ---
82 | apiVersion: apps/v1
83 | kind: Deployment
84 | metadata:
85 | name: devportal
86 | namespace: nginx-dapi
87 | labels:
88 | app: nap-compiler
89 | spec:
90 | selector:
91 | matchLabels:
92 | app: nap-compiler
93 | replicas: 1
94 | template:
95 | metadata:
96 | labels:
97 | app: nap-compiler
98 | spec:
99 | containers:
100 | - name: devportal
101 | image: YOUR_REGISTRY_HERE/nginx-declarative-api-nap-compiler:latest
102 | ports:
103 | - name: http
104 | containerPort: 5000
105 |
106 | ---
107 | apiVersion: v1
108 | kind: Service
109 | metadata:
110 | name: redis
111 | namespace: nginx-dapi
112 | labels:
113 | app: redis
114 | spec:
115 | ports:
116 | - name: redis
117 | port: 6379
118 | selector:
119 | app: redis
120 | type: ClusterIP
121 |
122 | ---
123 | apiVersion: v1
124 | kind: Service
125 | metadata:
126 | name: nginx-dapi
127 | namespace: nginx-dapi
128 | labels:
129 | app: nginx-dapi
130 | spec:
131 | ports:
132 | - name: http
133 | port: 5000
134 | selector:
135 | app: nginx-dapi
136 | type: ClusterIP
137 |
138 | ---
139 | apiVersion: v1
140 | kind: Service
141 | metadata:
142 | name: devportal
143 | namespace: nginx-dapi
144 | labels:
145 | app: devportal
146 | spec:
147 | ports:
148 | - name: http
149 | port: 5000
150 | selector:
151 | app: devportal
152 | type: ClusterIP
153 |
154 | ---
155 | apiVersion: v1
156 | kind: Service
157 | metadata:
158 | name: nap-compiler
159 | namespace: nginx-dapi
160 | labels:
161 | app: nap-compiler
162 | spec:
163 | ports:
164 | - name: http
165 | port: 5000
166 | selector:
167 | app: devportal
168 | type: ClusterIP
169 |
170 | ---
171 | apiVersion: networking.k8s.io/v1
172 | kind: Ingress
173 | metadata:
174 | name: nginx-dapi
175 | namespace: nginx-dapi
176 | labels:
177 | app: nginx-dapi
178 | spec:
179 | ingressClassName: nginx
180 | rules:
181 | - host: nginx-dapi.k8s.f5.ff.lan
182 | http:
183 | paths:
184 | - path: /
185 | pathType: Prefix
186 | backend:
187 | service:
188 | name: nginx-dapi
189 | port:
190 | number: 5000
191 |
--------------------------------------------------------------------------------
/contrib/postman/README.md:
--------------------------------------------------------------------------------
1 | # Sample Postman Collection
2 |
3 | This collection contains several declaration examples for the following Declarative API releases:
4 |
5 | * API v5.2 - Required for NGINX Plus R33+
6 | * API v5.1
7 | * API v5.0
8 |
9 | **Note**: NGINX Plus R33 and above [require a valid license](https://docs.nginx.com/solutions/about-subscription-licenses/) and the `.output.license` section in the declarative JSON is required. See the [usage notes](/USAGE-v5.2.md) for further details. [Postman collection](/contrib/postman) examples are provided for R33.
10 |
11 | ---
12 |
13 | ## API Gateway ##
14 |
15 | Test requests for the `API Gateway` folder in the Postman collection require `apigw.nginx.lab` to resolve to the NGINX instance IP address.
16 |
17 | ### Petstore ###
18 |
19 | Successful request
20 |
21 | ```
22 | curl -w '\n' -ik https://apigw.nginx.lab/petstore/store/inventory
23 | ```
24 |
25 | Authentication failed:
26 |
27 | ```
28 | curl -w '\n' -ik https://apigw.nginx.lab/petstore/user/login
29 | ```
30 |
31 | Authentication successful:
32 |
33 | ```
34 | curl -w '\n' -ik https://apigw.nginx.lab/petstore/user/login -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjAwMDEiLCJpc3MiOiJCYXNoIEpXVCBHZW5lcmF0b3IiLCJpYXQiOjE3MDI0ODEzNjcsImV4cCI6MTcwMjQ4MTM2OH0.eyJuYW1lIjoiQm9iIERldk9wcyIsInN1YiI6IkpXVCBzdWIgY2xhaW0iLCJpc3MiOiJKV1QgaXNzIGNsYWltIiwicm9sZXMiOlsiZGV2b3BzIl19.SKA_7MszAypMEtX5NDQ0TcUbVYx_Wt0hrtmuyTmrVKU"
35 | ```
36 |
37 | Authorization failed (based on JWT `role` claim):
38 |
39 | ```
40 | curl -w '\n' -ki https://apigw.nginx.lab/petstore/user/login -H "Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjAwMDEiLCJpc3MiOiJCYXNoIEpXVCBHZW5lcmF0b3IiLCJpYXQiOjE3MDk3NjQ3NTMsImV4cCI6MTcwOTc2NDc1NH0.eyJuYW1lIjoiQWxpY2UgR3Vlc3QiLCJzdWIiOiJKV1Qgc3ViIGNsYWltIiwiaXNzIjoiSldUIGlzcyBjbGFpbSIsInJvbGVzIjpbImd1ZXN0Il19.jFJDq-33irz7uFxdI8c8fIb5TwTAU5BlemmIFVALUAE"
41 | ```
42 | ```
43 | curl -w '\n' -ki https://apigw.nginx.lab/petstore/pet/1/uploadImage -X POST \
44 | -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjAwMDEiLCJpc3MiOiJCYXNoIEpXVCBHZW5lcmF0b3IiLCJpYXQiOjE3MDk3NjQ3NTMsImV4cCI6MTcwOTc2NDc1NH0.eyJuYW1lIjoiQWxpY2UgR3Vlc3QiLCJzdWIiOiJKV1Qgc3ViIGNsYWltIiwiaXNzIjoiSldUIGlzcyBjbGFpbSIsInJvbGVzIjpbImd1ZXN0Il19.jFJDq-33irz7uFxdI8c8fIb5TwTAU5BlemmIFVALUAE" \
45 | -H 'accept: application/json' \
46 | -H 'Content-Type: multipart/form-data' \
47 | -F 'file=iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAABhGlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV9TS0UqChYRcchQXbSLijjWKhShQqgVWnUwuX5Ck4YkxcVRcC04+LFYdXBx1tXBVRAEP0CcHZwUXaTE/yWFFjEeHPfj3b3H3TtAaFSYanbFAFWzjFQiLmayq2LwFQEI6Mc4BmVm6nOSlITn+LqHj693UZ7lfe7P0ZvLmwzwicQxphsW8QbxzKalc94nDrOSnCM+J54w6ILEj1xXXH7jXHRY4JlhI52aJw4Ti8UOVjqYlQyVeJo4klM1yhcyLuc4b3FWKzXWuid/YSivrSxzneYIEljEEiSIUFBDGRVYiNKqkWIiRftxD/+w45fIpZCrDEaOBVShQnb84H/wu1uzMDXpJoXiQODFtj9GgeAu0Kzb9vexbTdPAP8zcKW1/dUGMPtJer2tRY6Avm3g4rqtKXvA5Q4w9KTLhuxIfppCoQC8n9E3ZYGBW6Bnze2ttY/TByBNXSVvgINDYKxI2ese7+7u7O3fM63+fgB5bXKpzZcBIwAAAAlwSFlzAAAuIwAALiMBeKU/dgAAAAd0SU1FB+gFAhArKAvJglcAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC;type=image/png'
48 | ```
49 |
50 | Authorization successful (based on JWT `role` claim):
51 |
52 | ```
53 | curl -w '\n' -ki https://apigw.nginx.lab/petstore/user/login -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjAwMDEiLCJpc3MiOiJCYXNoIEpXVCBHZW5lcmF0b3IiLCJpYXQiOjE3MDI0ODEzNjcsImV4cCI6MTcwMjQ4MTM2OH0.eyJuYW1lIjoiQm9iIERldk9wcyIsInN1YiI6IkpXVCBzdWIgY2xhaW0iLCJpc3MiOiJKV1QgaXNzIGNsYWltIiwicm9sZXMiOlsiZGV2b3BzIl19.SKA_7MszAypMEtX5NDQ0TcUbVYx_Wt0hrtmuyTmrVKU"
54 | ```
55 |
56 | ```
57 | curl -w '\n' -ki https://apigw.nginx.lab/petstore/pet/1/uploadImage -X POST \
58 | -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjAwMDEiLCJpc3MiOiJCYXNoIEpXVCBHZW5lcmF0b3IiLCJpYXQiOjE3MDI0ODEzNjcsImV4cCI6MTcwMjQ4MTM2OH0.eyJuYW1lIjoiQm9iIERldk9wcyIsInN1YiI6IkpXVCBzdWIgY2xhaW0iLCJpc3MiOiJKV1QgaXNzIGNsYWltIiwicm9sZXMiOlsiZGV2b3BzIl19.SKA_7MszAypMEtX5NDQ0TcUbVYx_Wt0hrtmuyTmrVKU" \
59 | -H 'accept: application/json' \
60 | -H 'Content-Type: multipart/form-data' \
61 | -F 'file=iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAABhGlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV9TS0UqChYRcchQXbSLijjWKhShQqgVWnUwuX5Ck4YkxcVRcC04+LFYdXBx1tXBVRAEP0CcHZwUXaTE/yWFFjEeHPfj3b3H3TtAaFSYanbFAFWzjFQiLmayq2LwFQEI6Mc4BmVm6nOSlITn+LqHj693UZ7lfe7P0ZvLmwzwicQxphsW8QbxzKalc94nDrOSnCM+J54w6ILEj1xXXH7jXHRY4JlhI52aJw4Ti8UOVjqYlQyVeJo4klM1yhcyLuc4b3FWKzXWuid/YSivrSxzneYIEljEEiSIUFBDGRVYiNKqkWIiRftxD/+w45fIpZCrDEaOBVShQnb84H/wu1uzMDXpJoXiQODFtj9GgeAu0Kzb9vexbTdPAP8zcKW1/dUGMPtJer2tRY6Avm3g4rqtKXvA5Q4w9KTLhuxIfppCoQC8n9E3ZYGBW6Bnze2ttY/TByBNXSVvgINDYKxI2ese7+7u7O3fM63+fgB5bXKpzZcBIwAAAAlwSFlzAAAuIwAALiMBeKU/dgAAAAd0SU1FB+gFAhArKAvJglcAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC;type=image/png'
62 | ```
63 |
64 | The API Developer portal can be accessed at:
65 |
66 | https://apigw.nginx.lab/petstore/petstore-devportal.html
67 |
68 | ### Ergast ###
69 |
70 | Valid request:
71 |
72 | curl -s http://apigw.nginx.lab/ergast/2023.json | jq
73 |
74 | Invalid request:
75 |
76 | curl -s http://apigw.nginx.lab/ergast/2023.json -X POST
77 |
78 |
79 | ---
80 |
81 | **Note**: The `GitOps autosync` folder requires either
82 | - an NGINX instance (OSS or Plus) reachable as `acme.gitlab.local` on port `80/TCP` using the sample configuration available here: [/contrib/sample-source-of-truth/ncg-nginx.conf](/contrib/sample-source-of-truth/ncg-nginx.conf)
83 | - access to the GitHub repository at https://github.com/f5devcentral/NGINX-Declarative-API/ to fetch files under https://github.com/f5devcentral/NGINX-Declarative-API/tree/main/contrib/gitops-examples/v4.0
84 |
--------------------------------------------------------------------------------
/etc/config.toml:
--------------------------------------------------------------------------------
1 | # NGINX Declarative API - https://github.com/f5devcentral/NGINX-Declarative-API/
2 |
3 | # Main variables
4 | [main]
5 | banner = "NGINX Declarative API"
6 | version = "5.3.0"
7 | url = "https://github.com/f5devcentral/NGINX-Declarative-API"
8 |
9 | # Templates
10 | [templates]
11 | root_dir = "../templates"
12 | nginxmain = "nginx-conf/nginx.conf"
13 | mimetypes = "nginx-conf/mime.types"
14 | license = "nginx-conf/license-key.tmpl"
15 |
16 | httpconf = "http.tmpl"
17 | apigwconf = "apigateway.tmpl"
18 | visibility_root = "visibility"
19 | streamconf = "stream.tmpl"
20 | configmap = "configmap.tmpl"
21 |
22 | auth_client_root = "authn/client"
23 | auth_server_root = "authn/server"
24 |
25 | authz_client_root = "authz/client"
26 |
27 | devportal_root = "devportal"
28 | misc_root = "misc"
29 |
30 | # NGINX Declarative API Server
31 | [apiserver]
32 | host = "0.0.0.0"
33 | port = 5000
34 |
35 | # Redis backend
36 | [redis]
37 | host = "redis"
38 | port = 6379
39 |
40 | # Redocly devportal helper
41 | [devportal]
42 | host = "devportal"
43 | port = 5000
44 | uri = "/v1/devportal"
45 |
46 | # NGINX App Protect
47 | [nap]
48 | cookie_protection_seed = "tBjtd3WXKqoKp27pfEBc"
49 | compiler_host = "nap-compiler"
50 | compiler_port = 5000
51 | compiler_uri = "/v1/compile/policy"
52 |
53 | # Staged configuration directories
54 | [nms]
55 | config_dir = '/etc/nginx'
56 | certs_dir = '/etc/nginx/ssl'
57 | apigw_dir = '/etc/nginx/apigateway'
58 | visibility_dir = '/etc/nginx/visibility'
59 | devportal_dir = '/etc/nginx/devportal'
60 | auth_client_dir = '/etc/nginx/authn/client'
61 | auth_server_dir = '/etc/nginx/authn/server'
62 | authz_client_dir = '/etc/nginx/authz/client'
63 | njs_dir = '/etc/nginx/njs'
64 | resolver_dir = '/etc/nginx/resolvers'
65 | upstream_http_dir = '/etc/nginx/upstreams/http'
66 | upstream_stream_dir = '/etc/nginx/upstreams/stream'
67 |
68 | # Time (in seconds) to wait to get status after committing a staged config
69 | staged_config_publish_waittime = 2
70 |
71 | # Time (in seconds) to wait between two subsequent asynchronous submissions publish requests through PATCH
72 | asynchronous_publish_waittime = 30
73 |
74 | # NGINX App Protect support
75 | nap_policies_dir = '/etc/nginx/waf/policies'
76 | nap_logformats_dir = '/etc/nginx/waf/logformats'
77 | nap_logformats_template = "logformat.tmpl"
78 | nap_policies_dir_pum = '/etc/nms'
79 | nap_logformats_dir_pum = '/etc/nms'
80 |
81 | # Staged configuration filenames
82 | staged_config_http_filename = 'conf.d/services.conf'
83 | staged_config_stream_filename = 'stream-conf.d/services.conf'
--------------------------------------------------------------------------------
/src/NcgConfig.py:
--------------------------------------------------------------------------------
1 | """
2 | Configuration singleton
3 | """
4 |
5 | import toml
6 |
7 |
8 | class NcgConfig(object):
9 | _instance = None
10 | config = {}
11 |
12 | def __new__(cls,configFile):
13 | if cls._instance is None:
14 | print(f'Reading configuration from {configFile}')
15 | cls._instance = super(cls, NcgConfig).__new__(cls)
16 |
17 | with open(configFile) as cfgFile:
18 | cls.config = toml.load(cfgFile)
19 |
20 | return cls._instance
21 |
--------------------------------------------------------------------------------
/src/NcgRedis.py:
--------------------------------------------------------------------------------
1 | """
2 | Redis singleton
3 | """
4 |
5 | import redis
6 | import sys
7 | import queue
8 |
9 |
10 | class NcgRedis(object):
11 | _instance = None
12 | redis
13 | asyncQueue = None
14 |
15 | # All submitted config declarations
16 | # For each entry key is the configUid
17 | # Value is:
18 | # - the threaded autosync job for autosync declarations
19 | # - "static" for declarations not in autosync mode
20 | declarationsList = {}
21 |
22 | def __new__(cls, host, port):
23 | if cls._instance is None:
24 | try:
25 | cls.redis = redis.Redis(host, port)
26 | print(f"Connecting to redis at {host}:{port}")
27 |
28 | cls.redis.set('NGINX_Declarative_API','test')
29 | cls.redis.delete('NGINX_Declarative_API')
30 |
31 | # Asynchronous queue
32 | cls.asyncQueue = queue.Queue()
33 | except Exception as e:
34 | print(f"Cannot connect to redis on {host}:{port} : {e}")
35 | sys.exit(1)
36 |
37 | cls._instance = super(cls, NcgRedis).__new__(cls)
38 |
39 | return cls._instance
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/requirements.txt:
--------------------------------------------------------------------------------
1 | fastapi
2 | uvicorn
3 | urllib3
4 | requests
5 | datetime
6 | pydantic
7 | jinja2
8 | jinja2-base64-filters
9 | toml
10 | requests
11 | redis
12 | uuid
13 | schedule
14 | future
15 | pyyaml
--------------------------------------------------------------------------------
/src/v5_1/APIGateway.py:
--------------------------------------------------------------------------------
1 | """
2 | API Gateway support functions
3 | """
4 |
5 | import json
6 |
7 | import v5_1.GitOps
8 | import v5_1.MiscUtils
9 | from v5_1.OpenAPIParser import OpenAPIParser
10 |
11 | # pydantic models
12 | from V5_1_NginxConfigDeclaration import *
13 |
14 |
15 | # Builds the declarative JSON for the API Gateway configuration
16 | # Return a tuple: status, description. If status = 200 things were successful
17 | def createAPIGateway(locationDeclaration: dict, authProfiles: Authentication={}):
18 | apiGwDeclaration = {}
19 |
20 | if locationDeclaration['apigateway']['openapi_schema']:
21 | status, apiSchemaString = v5_1.GitOps.getObjectFromRepo(object=locationDeclaration['apigateway']['openapi_schema'],
22 | authProfiles = authProfiles['server'] if 'server' in authProfiles else {}, base64Encode=False)
23 |
24 | if v5_1.MiscUtils.yaml_or_json(apiSchemaString['content']) == 'yaml':
25 | # YAML to JSON conversion
26 | apiSchemaString['content'] = v5_1.MiscUtils.yaml_to_json(apiSchemaString['content'])
27 |
28 | apiSchema = OpenAPIParser(json.loads(apiSchemaString['content']))
29 |
30 | apiGwDeclaration = {}
31 | apiGwDeclaration['location'] = locationDeclaration
32 | apiGwDeclaration['info'] = apiSchema.info()
33 | apiGwDeclaration['servers'] = apiSchema.servers()
34 | apiGwDeclaration['paths'] = apiSchema.paths()
35 | apiGwDeclaration['version'] = apiSchema.version()
36 |
37 | return 200, apiGwDeclaration, apiSchemaString['content']
--------------------------------------------------------------------------------
/src/v5_1/DevPortal.py:
--------------------------------------------------------------------------------
1 | """
2 | API Gateway Developer Portal support functions
3 | """
4 |
5 | import json
6 | import requests
7 | import base64
8 |
9 | # NGINX Declarative API modules
10 | from NcgConfig import NcgConfig
11 | import v5_1.GitOps
12 | import v5_1.MiscUtils
13 |
14 | # pydantic models
15 | from V5_1_NginxConfigDeclaration import *
16 |
17 | def buildDevPortal(openapischema):
18 | try:
19 | response = requests.post(f"http://{NcgConfig.config['devportal']['host']}:"
20 | f"{NcgConfig.config['devportal']['port']}{NcgConfig.config['devportal']['uri']}",
21 | headers={'Content-Type': 'application/json'}, data=openapischema)
22 | except Exception as e:
23 | return 400, ""
24 |
25 | return response.status_code, json.loads(response.text)
26 |
27 |
28 | # Builds the declarative JSON for the API Gateway configuration
29 | # Return a tuple: status, description. If status = 200 things were successful
30 | def createDevPortal(locationDeclaration: dict, authProfiles: Authentication={}):
31 | if locationDeclaration['apigateway']['openapi_schema']:
32 | status, apiSchemaString = v5_1.GitOps.getObjectFromRepo(
33 | object = locationDeclaration['apigateway']['openapi_schema'], authProfiles = authProfiles['server'] if 'server' in authProfiles else {}, base64Encode = False)
34 |
35 | if v5_1.MiscUtils.yaml_or_json(apiSchemaString['content']) == 'yaml':
36 | # YAML to JSON conversion
37 | status, devportalJSON = buildDevPortal(openapischema = v5_1.MiscUtils.yaml_to_json(apiSchemaString['content']))
38 | else:
39 | status, devportalJSON = buildDevPortal(openapischema = apiSchemaString['content'])
40 |
41 | if status == 200:
42 | devportalHTML = base64.b64encode(bytes(devportalJSON['devportal'], 'utf-8')).decode('utf-8')
43 | else:
44 | devportalHTML = ""
45 |
46 | return status, devportalHTML
--------------------------------------------------------------------------------
/src/v5_1/GitOps.py:
--------------------------------------------------------------------------------
1 | """
2 | GitOps support functions
3 | """
4 |
5 | import base64
6 | import requests
7 |
8 | from requests import ReadTimeout, HTTPError, Timeout, ConnectionError, ConnectTimeout
9 |
10 | # pydantic models
11 | from V5_1_NginxConfigDeclaration import *
12 |
13 |
14 | # Fetches a URL content
15 | def __fetchfromsourceoftruth__(url, headers = {} ):
16 | # Object is fetched from external repository
17 | try:
18 | reply = requests.get(url = url, headers = headers, verify=False)
19 | except (ConnectTimeout, HTTPError, ReadTimeout, Timeout, ConnectionError):
20 | return 408, "URL " + url + " unreachable"
21 |
22 | return reply.status_code, reply.text
23 |
24 |
25 | # If content starts with http(s):// fetches the object and return it b64-encoded by default.
26 | # base64Encode to be set to False to disable b64 encoding
27 | # Returns the status original content otherwise.
28 | # Return is a tuple: status_code, content
29 | def getObjectFromRepo(object: ObjectFromSourceOfTruth, authProfiles: Authentication={}, base64Encode: bool=True):
30 | status_code = 200
31 | response = object
32 |
33 | if object:
34 | if object['content'].lower().startswith(("http://","https://")):
35 | # Object is fetched from external repository
36 | headers = {}
37 |
38 | # Set server authentication if needed
39 | if authProfiles and 'server' in authProfiles and len(object['authentication'])>0:
40 | for authP in authProfiles['server']:
41 | if object['authentication'][0]['profile'] == authP['name']:
42 | # Sets up authentication
43 | if authP['type'].lower() == 'token':
44 |
45 | authToken = authP['token']['token']
46 | authTokenType = authP['token']['type']
47 |
48 | if authTokenType.lower() == 'bearer':
49 | headers['Authorization'] = f"Bearer {authToken}"
50 | elif authTokenType.lower() == 'basic':
51 | authTokenUsername = authP['token']['username']
52 | authTokenPassword = base64.b64decode(authP['token']['password']).decode('utf-8')
53 |
54 | headers['Authorization'] = f"Basic {base64.b64encode(str.encode(authTokenUsername + ':' + authTokenPassword)).decode('utf-8')}"
55 | elif authTokenType.lower() == 'header':
56 | authTokenLocation = authP['token']['location']
57 |
58 | headers[authTokenLocation] = authToken
59 |
60 | status_code, fetchedContent = __fetchfromsourceoftruth__(url = object['content'], headers = headers)
61 |
62 | if status_code == 200:
63 | if base64Encode == True:
64 | fetchedContent = base64.b64encode(bytes(fetchedContent, 'utf-8')).decode('utf-8')
65 | else:
66 | fetchedContent = bytes(fetchedContent, 'utf-8').decode("utf-8")
67 |
68 | response['content'] = fetchedContent
69 |
70 | return status_code, response
--------------------------------------------------------------------------------
/src/v5_1/MiscUtils.py:
--------------------------------------------------------------------------------
1 | """
2 | Support functions
3 | """
4 |
5 | import re
6 | import json
7 | import yaml
8 | import uuid
9 |
10 |
11 | def getDictKey(_dict: dict, key_lookup: str, separator='.'):
12 | """
13 | Searches for a nested key in a dictionary and returns its value, or None if nothing was found.
14 | key_lookup must be a string where each key is deparated by a given "separator" character, which by default is a dot
15 | """
16 | keys = key_lookup.split(separator)
17 | subdict = _dict
18 |
19 | for k in keys:
20 | subdict = subdict[k] if k in subdict else None
21 | if subdict is None:
22 | return None
23 |
24 | return subdict
25 |
26 | """
27 | Jinja2 regexp filter
28 | """
29 | def regex_replace(s, find, replace):
30 | return re.sub(find, replace, s)
31 |
32 | """
33 | JSON/YAML detection
34 | """
35 | def yaml_or_json(document: str):
36 | try:
37 | json.load(document)
38 | return 'json'
39 | except Exception:
40 | return 'yaml'
41 |
42 | """
43 | YAML to JSON conversion
44 | """
45 | def yaml_to_json(document: str):
46 | return json.dumps(yaml.safe_load(document))
47 |
48 |
49 | """
50 | JSON TO YAML conversion
51 | """
52 | def json_to_yaml(document: str):
53 | return yaml.dump(json.loads(document))
54 |
55 |
56 | """
57 | Returns a unique ID
58 | """
59 | def getuniqueid():
60 | return uuid.uuid4()
--------------------------------------------------------------------------------
/src/v5_1/NGINXOneUtils.py:
--------------------------------------------------------------------------------
1 | """
2 | NGINX One support functions
3 | """
4 |
5 | import requests
6 | import json
7 |
8 |
9 | # Fetch a cluster ID from NGINX One
10 | # Return None if not found
11 | def getConfigSyncGroupId(nOneUrl: str, nOneToken: str, nameSpace: str, configSyncGroupName: str):
12 | # Retrieve config sync group uid
13 | cSyncGroup = requests.get(url=f'{nOneUrl}/api/nginx/one/namespaces/{nameSpace}/config-sync-groups',
14 | verify=False, headers = {"Authorization": f"Bearer APIToken {nOneToken}"})
15 |
16 | if cSyncGroup.status_code != 200:
17 | if cSyncGroup.status_code == 401:
18 | return cSyncGroup.status_code, "NGINX One authentication failed"
19 | else:
20 | return cSyncGroup.status_code, f"Error fetching config sync group uid: {cSyncGroup.text}"
21 |
22 | # Get the instance group id
23 | igUid = None
24 | igJson = json.loads(cSyncGroup.text)
25 | for i in igJson['items']:
26 | if i['name'] == configSyncGroupName:
27 | igUid = i['object_id']
28 |
29 | if igUid is None:
30 | return 404, f"config sync group [{configSyncGroupName}] not found"
31 |
32 | return 200, igUid
33 |
--------------------------------------------------------------------------------
/src/v5_1/NIMUtils.py:
--------------------------------------------------------------------------------
1 | """
2 | NGINX Instance Manager support functions
3 | """
4 |
5 | import requests
6 | import json
7 |
8 |
9 | # Fetch an instance group UID from NGINX Instance Manager
10 | # Return None if not found
11 | def getNIMInstanceGroupUid(nmsUrl: str, nmsUsername: str, nmsPassword: str, instanceGroupName: str):
12 | # Retrieve instance group uid
13 | ig = requests.get(url=f'{nmsUrl}/api/platform/v1/instance-groups', auth=(nmsUsername, nmsPassword),
14 | verify=False)
15 |
16 | if ig.status_code != 200:
17 | return None
18 |
19 | # Get the instance group id
20 | igUid = None
21 | igJson = json.loads(ig.text)
22 | for i in igJson['items']:
23 | if i['name'] == instanceGroupName:
24 | igUid = i['uid']
25 |
26 | return igUid
27 |
--------------------------------------------------------------------------------
/src/v5_1/OpenAPIParser.py:
--------------------------------------------------------------------------------
1 | """
2 | OpenAPI schema parser support functions
3 | """
4 |
5 | import json
6 |
7 | class OpenAPIParser:
8 | httpMethods = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH']
9 |
10 | def __init__(self, openAPISchema):
11 | self.openAPISchema = openAPISchema
12 |
13 | def version(self):
14 | if 'openapi' in self.openAPISchema:
15 | return self.openAPISchema['openapi']
16 | elif 'swagger' in self.openAPISchema:
17 | return self.openAPISchema['swagger']
18 |
19 | return None
20 |
21 | def info(self):
22 | return self.openAPISchema['info']
23 |
24 | def servers(self):
25 | self.allServers = []
26 |
27 | # Loop over OpenAPI schema servers
28 | if 'servers' in self.openAPISchema:
29 | for server in self.openAPISchema['servers']:
30 | urlName = server['url']
31 | self.s = {}
32 | self.s['url'] = urlName
33 |
34 | if 'description' in server:
35 | self.s['description'] = server['description']
36 |
37 | self.allServers.append(self.s)
38 |
39 | return self.allServers
40 |
41 | def paths(self):
42 | self.allPaths = []
43 |
44 | # Loop over OpenAPI schema paths
45 | if 'paths' in self.openAPISchema:
46 | for path in self.openAPISchema['paths'].keys():
47 | #print(f"- {path}")
48 | self.p = {}
49 | self.p['path'] = path
50 | self.p['methods'] = []
51 |
52 | # Loop over path HTTP methods found in schema
53 | for method in self.openAPISchema['paths'][path].keys():
54 | methodInfo = self.openAPISchema['paths'][path][method]
55 |
56 | if method.upper() in self.httpMethods:
57 | self.m = {}
58 | self.m['method'] = method
59 | self.m['details'] = {}
60 |
61 | if 'description' in methodInfo and methodInfo['description']:
62 | self.m['details']['description'] = methodInfo['description']
63 | if 'operationId' in methodInfo and methodInfo['operationId']:
64 | self.m['details']['operationId'] = methodInfo['operationId']
65 |
66 | self.p['methods'].append(self.m)
67 |
68 | self.allPaths.append(self.p)
69 |
70 | return self.allPaths
--------------------------------------------------------------------------------
/src/v5_2/APIGateway.py:
--------------------------------------------------------------------------------
1 | """
2 | API Gateway support functions
3 | """
4 |
5 | import json
6 |
7 | import v5_2.GitOps
8 | import v5_2.MiscUtils
9 | from v5_2.OpenAPIParser import OpenAPIParser
10 |
11 | # pydantic models
12 | # pydantic models
13 | from V5_2_NginxConfigDeclaration import *
14 |
15 |
16 | # Builds the declarative JSON for the API Gateway configuration
17 | # Return a tuple: status, description. If status = 200 things were successful
18 | def createAPIGateway(locationDeclaration: dict, authProfiles: Authentication={}):
19 | apiGwDeclaration = {}
20 |
21 | if locationDeclaration['apigateway']['openapi_schema']:
22 | status, apiSchemaString = v5_2.GitOps.getObjectFromRepo(object=locationDeclaration['apigateway']['openapi_schema'],
23 | authProfiles = authProfiles['server'] if 'server' in authProfiles else {}, base64Encode=False)
24 |
25 | if v5_2.MiscUtils.yaml_or_json(apiSchemaString['content']) == 'yaml':
26 | # YAML to JSON conversion
27 | apiSchemaString['content'] = v5_2.MiscUtils.yaml_to_json(apiSchemaString['content'])
28 |
29 | apiSchema = OpenAPIParser(json.loads(apiSchemaString['content']))
30 |
31 | apiGwDeclaration = {}
32 | apiGwDeclaration['location'] = locationDeclaration
33 | apiGwDeclaration['info'] = apiSchema.info()
34 | apiGwDeclaration['servers'] = apiSchema.servers()
35 | apiGwDeclaration['paths'] = apiSchema.paths()
36 | apiGwDeclaration['version'] = apiSchema.version()
37 |
38 | return 200, apiGwDeclaration, apiSchemaString['content']
--------------------------------------------------------------------------------
/src/v5_2/DevPortal.py:
--------------------------------------------------------------------------------
1 | """
2 | API Gateway Developer Portal support functions
3 | """
4 |
5 | import json
6 | import requests
7 | import base64
8 |
9 | # NGINX Declarative API modules
10 | from NcgConfig import NcgConfig
11 | import v5_2.GitOps
12 | import v5_2.MiscUtils
13 |
14 | # pydantic models
15 | from V5_2_NginxConfigDeclaration import *
16 |
17 | def buildDevPortal(openapischema):
18 | try:
19 | response = requests.post(f"http://{NcgConfig.config['devportal']['host']}:"
20 | f"{NcgConfig.config['devportal']['port']}{NcgConfig.config['devportal']['uri']}",
21 | headers={'Content-Type': 'application/json'}, data=openapischema)
22 | except Exception as e:
23 | return 400, ""
24 |
25 | return response.status_code, json.loads(response.text)
26 |
27 |
28 | # Builds the declarative JSON for the API Gateway configuration
29 | # Return a tuple: status, description. If status = 200 things were successful
30 | def createDevPortal(locationDeclaration: dict, authProfiles: Authentication={}):
31 | if locationDeclaration['apigateway']['openapi_schema']:
32 | status, apiSchemaString = v5_2.GitOps.getObjectFromRepo(
33 | object = locationDeclaration['apigateway']['openapi_schema'], authProfiles = authProfiles['server'] if 'server' in authProfiles else {}, base64Encode = False)
34 |
35 | if v5_2.MiscUtils.yaml_or_json(apiSchemaString['content']) == 'yaml':
36 | # YAML to JSON conversion
37 | status, devportalJSON = buildDevPortal(openapischema = v5_2.MiscUtils.yaml_to_json(apiSchemaString['content']))
38 | else:
39 | status, devportalJSON = buildDevPortal(openapischema = apiSchemaString['content'])
40 |
41 | if status == 200:
42 | devportalHTML = base64.b64encode(bytes(devportalJSON['devportal'], 'utf-8')).decode('utf-8')
43 | else:
44 | devportalHTML = ""
45 |
46 | return status, devportalHTML
--------------------------------------------------------------------------------
/src/v5_2/GitOps.py:
--------------------------------------------------------------------------------
1 | """
2 | GitOps support functions
3 | """
4 |
5 | import base64
6 | import requests
7 |
8 | from requests import ReadTimeout, HTTPError, Timeout, ConnectionError, ConnectTimeout
9 |
10 | # pydantic models
11 | from V5_2_NginxConfigDeclaration import *
12 |
13 |
14 | # Fetches a URL content
15 | def __fetchfromsourceoftruth__(url, headers = {} ):
16 | # Object is fetched from external repository
17 |
18 | try:
19 | reply = requests.get(url = url, headers = headers, verify=False)
20 | except (ConnectTimeout, HTTPError, ReadTimeout, Timeout, ConnectionError):
21 | return 408, "URL " + url + " unreachable"
22 |
23 | return reply.status_code, reply.text
24 |
25 |
26 | # If content starts with http(s):// fetches the object and return it b64-encoded by default.
27 | # base64Encode to be set to False to disable b64 encoding
28 | # Returns the status original content otherwise.
29 | # Return is a tuple: status_code, content
30 | def getObjectFromRepo(object: ObjectFromSourceOfTruth, authProfiles: Authentication={}, base64Encode: bool=True):
31 | status_code = 200
32 | response = object
33 |
34 | if object:
35 | if object['content'].lower().startswith(("http://","https://")):
36 | # Object is fetched from external repository
37 | headers = {}
38 |
39 | # Set server authentication if needed
40 | if authProfiles and 'server' in authProfiles and len(object['authentication'])>0:
41 | for authP in authProfiles['server']:
42 | if object['authentication'][0]['profile'] == authP['name']:
43 | # Sets up authentication
44 | if authP['type'].lower() == 'token':
45 |
46 | authToken = authP['token']['token']
47 | authTokenType = authP['token']['type']
48 |
49 | if authTokenType.lower() == 'bearer':
50 | headers['Authorization'] = f"Bearer {authToken}"
51 | elif authTokenType.lower() == 'basic':
52 | authTokenUsername = authP['token']['username']
53 | authTokenPassword = base64.b64decode(authP['token']['password']).decode('utf-8')
54 |
55 | headers['Authorization'] = f"Basic {base64.b64encode(str.encode(authTokenUsername + ':' + authTokenPassword)).decode('utf-8')}"
56 | elif authTokenType.lower() == 'header':
57 | authTokenLocation = authP['token']['location']
58 |
59 | headers[authTokenLocation] = authToken
60 |
61 | status_code, fetchedContent = __fetchfromsourceoftruth__(url = object['content'], headers = headers)
62 |
63 | if status_code == 200:
64 | if base64Encode == True:
65 | fetchedContent = base64.b64encode(bytes(fetchedContent, 'utf-8')).decode('utf-8')
66 | else:
67 | fetchedContent = bytes(fetchedContent, 'utf-8').decode("utf-8")
68 |
69 | response['content'] = fetchedContent
70 |
71 | return status_code, response
--------------------------------------------------------------------------------
/src/v5_2/MiscUtils.py:
--------------------------------------------------------------------------------
1 | """
2 | Support functions
3 | """
4 |
5 | import re
6 | import json
7 | import yaml
8 | import uuid
9 | import socket
10 |
11 |
12 | # Searches for a nested key in a dictionary and returns its value, or None if nothing was found.
13 | # key_lookup must be a string where each key is deparated by a given "separator" character, which by default is a dot
14 | def getDictKey(_dict: dict, key_lookup: str, separator='.'):
15 | keys = key_lookup.split(separator)
16 | subdict = _dict
17 |
18 | for k in keys:
19 | subdict = subdict[k] if k in subdict else None
20 | if subdict is None:
21 | return None
22 |
23 | return subdict
24 |
25 | # Jinja2 regexp filter
26 | def regex_replace(s, find, replace):
27 | return re.sub(find, replace, s)
28 |
29 | # JSON/YAML detection
30 | def yaml_or_json(document: str):
31 | try:
32 | json.load(document)
33 | return 'json'
34 | except Exception:
35 | return 'yaml'
36 |
37 | # YAML to JSON conversion
38 | def yaml_to_json(document: str):
39 | return json.dumps(yaml.safe_load(document))
40 |
41 |
42 | # JSON TO YAML conversion
43 | def json_to_yaml(document: str):
44 | return yaml.dump(json.loads(document))
45 |
46 |
47 | # Returns a unique ID
48 | def getuniqueid():
49 | return uuid.uuid4()
50 |
51 |
52 | # Test DNS resolution
53 | # Returns {True,IP address} if successful and {False,error description} for NXDOMAIN/if DNS resolution failed
54 | def resolveFQDN(fqdn:str):
55 | try:
56 | return True,socket.gethostbyname(fqdn)
57 | except Exception as e:
58 | return False,e
59 |
60 |
--------------------------------------------------------------------------------
/src/v5_2/NGINXOneUtils.py:
--------------------------------------------------------------------------------
1 | """
2 | NGINX One support functions
3 | """
4 |
5 | import requests
6 | import json
7 |
8 |
9 | # Fetch a cluster ID from NGINX One
10 | # Return None if not found
11 | def getConfigSyncGroupId(nOneUrl: str, nOneToken: str, nameSpace: str, configSyncGroupName: str):
12 | # Retrieve config sync group uid
13 | cSyncGroup = requests.get(url=f'{nOneUrl}/api/nginx/one/namespaces/{nameSpace}/config-sync-groups',
14 | verify=False, headers = {"Authorization": f"Bearer APIToken {nOneToken}"})
15 |
16 | if cSyncGroup.status_code != 200:
17 | if cSyncGroup.status_code == 401:
18 | return cSyncGroup.status_code, "NGINX One authentication failed"
19 | else:
20 | return cSyncGroup.status_code, f"Error fetching config sync group uid: {cSyncGroup.text}"
21 |
22 | # Get the instance group id
23 | igUid = None
24 | igJson = json.loads(cSyncGroup.text)
25 | for i in igJson['items']:
26 | if i['name'] == configSyncGroupName:
27 | igUid = i['object_id']
28 |
29 | if igUid is None:
30 | return 404, f"config sync group [{configSyncGroupName}] not found"
31 |
32 | return 200, igUid
33 |
--------------------------------------------------------------------------------
/src/v5_2/NIMUtils.py:
--------------------------------------------------------------------------------
1 | """
2 | NGINX Instance Manager support functions
3 | """
4 |
5 | import requests
6 | import json
7 |
8 |
9 | # Fetch an instance group UID from NGINX Instance Manager
10 | # Return None if not found
11 | def getNIMInstanceGroupUid(nmsUrl: str, nmsUsername: str, nmsPassword: str, instanceGroupName: str):
12 | # Retrieve instance group uid
13 | ig = requests.get(url=f'{nmsUrl}/api/platform/v1/instance-groups', auth=(nmsUsername, nmsPassword),
14 | verify=False)
15 |
16 | if ig.status_code != 200:
17 | return None
18 |
19 | # Get the instance group id
20 | igUid = None
21 | igJson = json.loads(ig.text)
22 | for i in igJson['items']:
23 | if i['name'] == instanceGroupName:
24 | igUid = i['uid']
25 |
26 | return igUid
27 |
--------------------------------------------------------------------------------
/src/v5_2/OpenAPIParser.py:
--------------------------------------------------------------------------------
1 | """
2 | OpenAPI schema parser support functions
3 | """
4 |
5 | import json
6 |
7 | class OpenAPIParser:
8 | httpMethods = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH']
9 |
10 | def __init__(self, openAPISchema):
11 | self.openAPISchema = openAPISchema
12 |
13 | def version(self):
14 | if 'openapi' in self.openAPISchema:
15 | return self.openAPISchema['openapi']
16 | elif 'swagger' in self.openAPISchema:
17 | return self.openAPISchema['swagger']
18 |
19 | return None
20 |
21 | def info(self):
22 | return self.openAPISchema['info']
23 |
24 | def servers(self):
25 | self.allServers = []
26 |
27 | # Loop over OpenAPI schema servers
28 | if 'servers' in self.openAPISchema:
29 | for server in self.openAPISchema['servers']:
30 | urlName = server['url']
31 | self.s = {}
32 | self.s['url'] = urlName
33 |
34 | if 'description' in server:
35 | self.s['description'] = server['description']
36 |
37 | self.allServers.append(self.s)
38 |
39 | return self.allServers
40 |
41 | def paths(self):
42 | self.allPaths = []
43 |
44 | # Loop over OpenAPI schema paths
45 | if 'paths' in self.openAPISchema:
46 | for path in self.openAPISchema['paths'].keys():
47 | #print(f"- {path}")
48 | self.p = {}
49 | self.p['path'] = path
50 | self.p['methods'] = []
51 |
52 | # Loop over path HTTP methods found in schema
53 | for method in self.openAPISchema['paths'][path].keys():
54 | methodInfo = self.openAPISchema['paths'][path][method]
55 |
56 | if method.upper() in self.httpMethods:
57 | self.m = {}
58 | self.m['method'] = method
59 | self.m['details'] = {}
60 |
61 | if 'description' in methodInfo and methodInfo['description']:
62 | self.m['details']['description'] = methodInfo['description']
63 | if 'operationId' in methodInfo and methodInfo['operationId']:
64 | self.m['details']['operationId'] = methodInfo['operationId']
65 |
66 | self.p['methods'].append(self.m)
67 |
68 | self.allPaths.append(self.p)
69 |
70 | return self.allPaths
--------------------------------------------------------------------------------
/src/v5_3/APIGateway.py:
--------------------------------------------------------------------------------
1 | """
2 | API Gateway support functions
3 | """
4 |
5 | import json
6 |
7 | import v5_3.GitOps
8 | import v5_3.MiscUtils
9 | from v5_3.OpenAPIParser import OpenAPIParser
10 |
11 | # pydantic models
12 | from V5_3_NginxConfigDeclaration import *
13 |
14 |
15 | # Builds the declarative JSON for the API Gateway configuration
16 | # Return a tuple: status, description. If status = 200 things were successful
17 | def createAPIGateway(locationDeclaration: dict, authProfiles: Authentication={}):
18 | apiGwDeclaration = {}
19 |
20 | if locationDeclaration['apigateway']['openapi_schema']:
21 | status, apiSchemaString = v5_3.GitOps.getObjectFromRepo(object=locationDeclaration['apigateway']['openapi_schema'],
22 | authProfiles = authProfiles['server'] if 'server' in authProfiles else {}, base64Encode=False)
23 |
24 | if v5_3.MiscUtils.yaml_or_json(apiSchemaString['content']) == 'yaml':
25 | # YAML to JSON conversion
26 | apiSchemaString['content'] = v5_3.MiscUtils.yaml_to_json(apiSchemaString['content'])
27 |
28 | apiSchema = OpenAPIParser(json.loads(apiSchemaString['content']))
29 |
30 | apiGwDeclaration = {}
31 | apiGwDeclaration['location'] = locationDeclaration
32 | apiGwDeclaration['info'] = apiSchema.info()
33 | apiGwDeclaration['servers'] = apiSchema.servers()
34 | apiGwDeclaration['paths'] = apiSchema.paths()
35 | apiGwDeclaration['version'] = apiSchema.version()
36 |
37 | return 200, apiGwDeclaration, apiSchemaString['content']
--------------------------------------------------------------------------------
/src/v5_3/Asynchronous.py:
--------------------------------------------------------------------------------
1 | """"
2 | Asynchronous declarations support
3 | """
4 | import json
5 | import pickle
6 |
7 | import v5_3.MiscUtils
8 | from NcgRedis import NcgRedis
9 |
10 | # pydantic models
11 | from V5_3_NginxConfigDeclaration import ConfigDeclaration
12 |
13 | #
14 | # Check if the incoming request is asynchronous
15 | #
16 | def checkIfAsynch(declaration: ConfigDeclaration, method: str, apiVersion: str, configUid: str):
17 | djson = declaration.model_dump()
18 |
19 | if djson['output']['synchronous']:
20 | # Synchronous declaration, normal processing
21 | return None, None
22 |
23 | # Asynchronous declaration, submit to FIFO queue
24 | submissionUid = str(v5_3.MiscUtils.getuniqueid())
25 | submissionPayload = {'declaration': declaration, 'method': method, 'configUid': configUid, "apiVersion": apiVersion, "submissionUid": submissionUid}
26 | NcgRedis.asyncQueue.put(submissionPayload)
27 |
28 | response = {}
29 | response['code'] = 202
30 | response['message'] = f'Declaration submitted'
31 | response['configUid'] = configUid
32 | response['submissionUid'] = submissionUid
33 |
34 | NcgRedis.redis.set(f'ncg.async.submission.{submissionUid}', json.dumps(response))
35 |
36 | return 202, response
--------------------------------------------------------------------------------
/src/v5_3/DevPortal.py:
--------------------------------------------------------------------------------
1 | """
2 | API Gateway Developer Portal support functions
3 | """
4 |
5 | import json
6 | import requests
7 | import base64
8 |
9 | # NGINX Declarative API modules
10 | from NcgConfig import NcgConfig
11 | import v5_3.GitOps
12 | import v5_3.MiscUtils
13 |
14 | # pydantic models
15 | from V5_3_NginxConfigDeclaration import *
16 |
17 | def buildDevPortal(openapischema):
18 | try:
19 | response = requests.post(f"http://{NcgConfig.config['devportal']['host']}:"
20 | f"{NcgConfig.config['devportal']['port']}{NcgConfig.config['devportal']['uri']}",
21 | headers={'Content-Type': 'application/json'}, data=openapischema)
22 | except Exception as e:
23 | return 400, ""
24 |
25 | return response.status_code, json.loads(response.text)
26 |
27 |
28 | # Builds the declarative JSON for the API Gateway configuration
29 | # Return a tuple: status, description. If status = 200 things were successful
30 | def createDevPortal(locationDeclaration: dict, authProfiles: Authentication={}):
31 | if locationDeclaration['apigateway']['openapi_schema']:
32 | status, apiSchemaString = v5_3.GitOps.getObjectFromRepo(
33 | object = locationDeclaration['apigateway']['openapi_schema'], authProfiles = authProfiles['server'] if 'server' in authProfiles else {}, base64Encode = False)
34 |
35 | if v5_3.MiscUtils.yaml_or_json(apiSchemaString['content']) == 'yaml':
36 | # YAML to JSON conversion
37 | status, devportalJSON = buildDevPortal(openapischema = v5_3.MiscUtils.yaml_to_json(apiSchemaString['content']))
38 | else:
39 | status, devportalJSON = buildDevPortal(openapischema = apiSchemaString['content'])
40 |
41 | if status == 200:
42 | devportalHTML = base64.b64encode(bytes(devportalJSON['devportal'], 'utf-8')).decode('utf-8')
43 | else:
44 | devportalHTML = ""
45 |
46 | return status, devportalHTML
--------------------------------------------------------------------------------
/src/v5_3/GitOps.py:
--------------------------------------------------------------------------------
1 | """
2 | GitOps support functions
3 | """
4 |
5 | import base64
6 | import requests
7 |
8 | from requests import ReadTimeout, HTTPError, Timeout, ConnectionError, ConnectTimeout
9 |
10 | # pydantic models
11 | from V5_3_NginxConfigDeclaration import *
12 |
13 |
14 | # Fetches a URL content
15 | def __fetchfromsourceoftruth__(url, headers = {} ):
16 | # Object is fetched from external repository
17 |
18 | try:
19 | reply = requests.get(url = url, headers = headers, verify=False)
20 | except (ConnectTimeout, HTTPError, ReadTimeout, Timeout, ConnectionError):
21 | return 408, "URL " + url + " unreachable"
22 |
23 | return reply.status_code, reply.text
24 |
25 |
26 | # If content starts with http(s):// fetches the object and return it b64-encoded by default.
27 | # base64Encode to be set to False to disable b64 encoding
28 | # Returns the status original content otherwise.
29 | # Return is a tuple: status_code, content
30 | def getObjectFromRepo(object: ObjectFromSourceOfTruth, authProfiles: Authentication={}, base64Encode: bool=True):
31 | status_code = 200
32 | response = object
33 |
34 | if object:
35 | if object['content'].lower().startswith(("http://","https://")):
36 | # Object is fetched from external repository
37 | headers = {}
38 |
39 | # Set server authentication if needed
40 | if authProfiles and 'server' in authProfiles and len(object['authentication'])>0:
41 | for authP in authProfiles['server']:
42 | if object['authentication'][0]['profile'] == authP['name']:
43 | # Sets up authentication
44 | if authP['type'].lower() == 'token':
45 |
46 | authToken = authP['token']['token']
47 | authTokenType = authP['token']['type']
48 |
49 | if authTokenType.lower() == 'bearer':
50 | headers['Authorization'] = f"Bearer {authToken}"
51 | elif authTokenType.lower() == 'basic':
52 | authTokenUsername = authP['token']['username']
53 | authTokenPassword = base64.b64decode(authP['token']['password']).decode('utf-8')
54 |
55 | headers['Authorization'] = f"Basic {base64.b64encode(str.encode(authTokenUsername + ':' + authTokenPassword)).decode('utf-8')}"
56 | elif authTokenType.lower() == 'header':
57 | authTokenLocation = authP['token']['location']
58 |
59 | headers[authTokenLocation] = authToken
60 |
61 | status_code, fetchedContent = __fetchfromsourceoftruth__(url = object['content'], headers = headers)
62 |
63 | if status_code == 200:
64 | if base64Encode == True:
65 | fetchedContent = base64.b64encode(bytes(fetchedContent, 'utf-8')).decode('utf-8')
66 | else:
67 | fetchedContent = bytes(fetchedContent, 'utf-8').decode("utf-8")
68 |
69 | response['content'] = fetchedContent
70 |
71 | return status_code, response
--------------------------------------------------------------------------------
/src/v5_3/MiscUtils.py:
--------------------------------------------------------------------------------
1 | """
2 | Support functions
3 | """
4 |
5 | import re
6 | import json
7 | import yaml
8 | import uuid
9 | import socket
10 |
11 |
12 | # Searches for a nested key in a dictionary and returns its value, or None if nothing was found.
13 | # key_lookup must be a string where each key is deparated by a given "separator" character, which by default is a dot
14 | def getDictKey(_dict: dict, key_lookup: str, separator='.'):
15 | keys = key_lookup.split(separator)
16 | subdict = _dict
17 |
18 | for k in keys:
19 | subdict = subdict[k] if k in subdict else None
20 | if subdict is None:
21 | return None
22 |
23 | return subdict
24 |
25 | # Jinja2 regexp filter
26 | def regex_replace(s, find, replace):
27 | return re.sub(find, replace, s)
28 |
29 | # JSON/YAML detection
30 | def yaml_or_json(document: str):
31 | try:
32 | json.load(document)
33 | return 'json'
34 | except Exception:
35 | return 'yaml'
36 |
37 | # YAML to JSON conversion
38 | def yaml_to_json(document: str):
39 | return json.dumps(yaml.safe_load(document))
40 |
41 |
42 | # JSON TO YAML conversion
43 | def json_to_yaml(document: str):
44 | return yaml.dump(json.loads(document))
45 |
46 |
47 | # Returns a unique ID
48 | def getuniqueid():
49 | return uuid.uuid4()
50 |
51 |
52 | # Test DNS resolution
53 | # Returns {True,IP address} if successful and {False,error description} for NXDOMAIN/if DNS resolution failed
54 | def resolveFQDN(fqdn:str):
55 | try:
56 | return True,socket.gethostbyname(fqdn)
57 | except Exception as e:
58 | return False,e
59 |
60 |
--------------------------------------------------------------------------------
/src/v5_3/NGINXOneUtils.py:
--------------------------------------------------------------------------------
1 | """
2 | NGINX One support functions
3 | """
4 |
5 | import requests
6 | import json
7 |
8 |
9 | # Fetch a cluster ID from NGINX One
10 | # Return None if not found
11 | def getConfigSyncGroupId(nOneUrl: str, nOneToken: str, nameSpace: str, configSyncGroupName: str):
12 | # Retrieve config sync group uid
13 | cSyncGroup = requests.get(url=f'{nOneUrl}/api/nginx/one/namespaces/{nameSpace}/config-sync-groups?paginated=false',
14 | verify=False, headers = {"Authorization": f"Bearer APIToken {nOneToken}"})
15 |
16 | if cSyncGroup.status_code != 200:
17 | if cSyncGroup.status_code == 401:
18 | return cSyncGroup.status_code, "NGINX One authentication failed"
19 | else:
20 | return cSyncGroup.status_code, f"Error fetching config sync group uid: {cSyncGroup.text}"
21 |
22 | # Get the instance group id
23 | igUid = None
24 | igJson = json.loads(cSyncGroup.text)
25 | for i in igJson['items']:
26 | if i['name'] == configSyncGroupName:
27 | igUid = i['object_id']
28 |
29 | if igUid is None:
30 | return 404, f"config sync group [{configSyncGroupName}] not found"
31 |
32 | return 200, igUid
33 |
--------------------------------------------------------------------------------
/src/v5_3/NIMUtils.py:
--------------------------------------------------------------------------------
1 | """
2 | NGINX Instance Manager support functions
3 | """
4 |
5 | import requests
6 | import json
7 |
8 |
9 | # Fetch an instance group UID from NGINX Instance Manager
10 | # Return None if not found
11 | def getNIMInstanceGroupUid(nmsUrl: str, nmsUsername: str, nmsPassword: str, instanceGroupName: str):
12 | # Retrieve instance group uid
13 | ig = requests.get(url=f'{nmsUrl}/api/platform/v1/instance-groups', auth=(nmsUsername, nmsPassword),
14 | verify=False)
15 |
16 | if ig.status_code != 200:
17 | return None
18 |
19 | # Get the instance group id
20 | igUid = None
21 | igJson = json.loads(ig.text)
22 | for i in igJson['items']:
23 | if i['name'] == instanceGroupName:
24 | igUid = i['uid']
25 |
26 | return igUid
27 |
--------------------------------------------------------------------------------
/src/v5_3/OpenAPIParser.py:
--------------------------------------------------------------------------------
1 | """
2 | OpenAPI schema parser support functions
3 | """
4 |
5 | import json
6 |
7 | class OpenAPIParser:
8 | httpMethods = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH']
9 |
10 | def __init__(self, openAPISchema):
11 | self.openAPISchema = openAPISchema
12 |
13 | def version(self):
14 | if 'openapi' in self.openAPISchema:
15 | return self.openAPISchema['openapi']
16 | elif 'swagger' in self.openAPISchema:
17 | return self.openAPISchema['swagger']
18 |
19 | return None
20 |
21 | def info(self):
22 | return self.openAPISchema['info']
23 |
24 | def servers(self):
25 | self.allServers = []
26 |
27 | # Loop over OpenAPI schema servers
28 | if 'servers' in self.openAPISchema:
29 | for server in self.openAPISchema['servers']:
30 | urlName = server['url']
31 | self.s = {}
32 | self.s['url'] = urlName
33 |
34 | if 'description' in server:
35 | self.s['description'] = server['description']
36 |
37 | self.allServers.append(self.s)
38 |
39 | return self.allServers
40 |
41 | def paths(self):
42 | self.allPaths = []
43 |
44 | # Loop over OpenAPI schema paths
45 | if 'paths' in self.openAPISchema:
46 | for path in self.openAPISchema['paths'].keys():
47 | #print(f"- {path}")
48 | self.p = {}
49 | self.p['path'] = path
50 | self.p['methods'] = []
51 |
52 | # Loop over path HTTP methods found in schema
53 | for method in self.openAPISchema['paths'][path].keys():
54 | methodInfo = self.openAPISchema['paths'][path][method]
55 |
56 | if method.upper() in self.httpMethods:
57 | self.m = {}
58 | self.m['method'] = method
59 | self.m['details'] = {}
60 |
61 | if 'description' in methodInfo and methodInfo['description']:
62 | self.m['details']['description'] = methodInfo['description']
63 | if 'operationId' in methodInfo and methodInfo['operationId']:
64 | self.m['details']['operationId'] = methodInfo['operationId']
65 |
66 | self.p['methods'].append(self.m)
67 |
68 | self.allPaths.append(self.p)
69 |
70 | return self.allPaths
--------------------------------------------------------------------------------
/templates/v5.1/authn/client/jwks.tmpl:
--------------------------------------------------------------------------------
1 | location = /_auth/jwt/{{ authprofile.name | replace(" ", "_") }}/_jwks_uri {
2 | internal;
3 |
4 | {% if authprofile.jwt.key.startswith('http://') or authprofile.jwt.key.startswith('https://') -%}
5 | proxy_method GET;
6 | proxy_pass {{ authprofile.jwt.key }};
7 | {% else -%}
8 | return 200 '{{ authprofile.jwt.key }}';
9 | {%- endif %}
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/templates/v5.1/authn/client/jwt.tmpl:
--------------------------------------------------------------------------------
1 | auth_jwt "{{ authprofile.jwt.realm }}"{% if authprofile.jwt.token_location %} token={{ authprofile.jwt.token_location }}{% endif %};
2 | auth_jwt_type {{ authprofile.jwt.jwt_type }};
3 | auth_jwt_key_request /_auth/jwt/{{ authprofile.name | replace(" ", "_") }}/_jwks_uri;
4 | {% if authprofile.jwt.cachetime != 0 %}
5 | auth_jwt_key_cache {{ authprofile.jwt.cachetime }};
6 | {% endif %}
7 |
--------------------------------------------------------------------------------
/templates/v5.1/authn/client/mtls.tmpl:
--------------------------------------------------------------------------------
1 | {%- if authprofile.mtls.enabled|lower != "off" -%}
2 | ssl_verify_client {{ authprofile.mtls.enabled }};
3 | {% if authprofile.mtls.client_certificates -%}
4 | ssl_client_certificate {{ ncgconfig.nms.certs_dir }}/{{ authprofile.mtls.client_certificates }}.crt;
5 | {% endif %}
6 |
7 | {% if authprofile.mtls.trusted_ca_certificates -%}
8 | ssl_trusted_certificate {{ ncgconfig.nms.certs_dir }}/{{ authprofile.mtls.trusted_ca_certificates }}.crt;
9 | {% endif %}
10 |
11 | {# --- OCSP section start --- #}
12 | {%- if authprofile.mtls.ocsp and authprofile.mtls.ocsp.enabled|lower != "off" -%}
13 | ssl_ocsp {{ authprofile.mtls.ocsp.enabled }};
14 | {% if authprofile.mtls.ocsp.responder -%}
15 | ssl_ocsp_responder {{ authprofile.mtls.ocsp.responder }};
16 | {% endif %}
17 | {% endif %}
18 | {# --- OCSP section end --- #}
19 |
20 | {# --- TLS stapling section start --- #}
21 | {%- if authprofile.mtls.stapling and authprofile.mtls.stapling.enabled == True -%}
22 | ssl_stapling on;
23 | ssl_stapling_verify {% if authprofile.mtls.stapling.verify == True %}on{% else %}off{% endif %};
24 | {% if authprofile.mtls.stapling.responder -%}
25 | ssl_stapling_responder {{ authprofile.mtls.stapling.responder }};
26 | {% endif -%}
27 | {%- endif %}
28 | {# --- TLS stapling section end --- #}
29 | {% endif %}
--------------------------------------------------------------------------------
/templates/v5.1/authn/server/mtls.tmpl:
--------------------------------------------------------------------------------
1 | proxy_ssl_certificate {{ ncgconfig.nms.certs_dir }}/{{ authprofile.mtls.certificate }}.crt;
2 | proxy_ssl_certificate_key {{ ncgconfig.nms.certs_dir }}/{{ authprofile.mtls.certificate }}.key;
3 |
--------------------------------------------------------------------------------
/templates/v5.1/authn/server/token.tmpl:
--------------------------------------------------------------------------------
1 | {% if authprofile.token.type == "bearer" %}
2 | proxy_set_header Authorization "Bearer {{ authprofile.token.token }}";
3 | {% elif authprofile.token.type == "basic" %}
4 | proxy_set_header Authorization "Basic {{ (authprofile.token.username + ':' + (authprofile.token.password | b64decode) ) | b64encode }}";
5 | {% elif authprofile.token.type == "header" %}
6 | proxy_set_header {{ authprofile.token.location }} "{{ authprofile.token.token }}";
7 | {% endif %}
--------------------------------------------------------------------------------
/templates/v5.1/authz/client/jwt-authz-map.tmpl:
--------------------------------------------------------------------------------
1 | {% for claim in authprofile.jwt.claims %}
2 | auth_jwt_claim_set $authz_match_jwt_claim_{{ claim.name }}_{{ authprofile.name | replace(" ", "_") }} {{ claim.name }};
3 | {% endfor %}
4 |
5 | {% for claim in authprofile.jwt.claims %}
6 | # JWT claim {{ claim.name }} validation for profile "{{ authprofile.name }}"
7 | map $authz_match_jwt_claim_{{ claim.name }}_{{ authprofile.name | replace(" ", "_") }} $jwt_authz_claim_{{ claim.name }}_{{ authprofile.name | replace(" ", "_") }} {
8 | {% for value in claim.value %}
9 | "{{ value }}" 1;
10 | {% endfor %}
11 | default 0;
12 | }
13 |
14 | {% endfor %}
--------------------------------------------------------------------------------
/templates/v5.1/authz/client/jwt.tmpl:
--------------------------------------------------------------------------------
1 | {% for claim in authprofile.jwt.claims %}
2 | auth_jwt_require $jwt_authz_claim_{{ claim.name }}_{{ authprofile.name | replace(" ", "_") }} error={{ claim.errorcode }};
3 | {% endfor %}
--------------------------------------------------------------------------------
/templates/v5.1/configmap.tmpl:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: ConfigMap
3 | metadata:
4 | name: {{ name }}
5 | {% if namespace -%}
6 | namespace: {{ namespace }}
7 | {% endif %}
8 |
9 | data:
10 | {{ filename }}: |-
11 | {% filter indent(width = 4) %}
12 | {{ nginxconfig }}
13 | {% endfilter %}
--------------------------------------------------------------------------------
/templates/v5.1/devportal/backstage.tmpl:
--------------------------------------------------------------------------------
1 | apiVersion: backstage.io/v1alpha1
2 | kind: API
3 | metadata:
4 | name: {{ declaration.name }}
5 | annotations:
6 | github.com/project-slug: backstage/backstage
7 | backstage.io/techdocs-ref: dir:.
8 | lighthouse.com/website-url: https://backstage.io
9 | spec:
10 | type: openapi
11 | lifecycle: {{ declaration.lifecycle }}
12 | owner: {{ declaration.owner }}
13 | system: {{ declaration.system }}
14 | definition: |
15 | {% filter indent(width=4) %}
16 | {{ openAPISchema }}
17 | {% endfilter %}
--------------------------------------------------------------------------------
/templates/v5.1/logformat.tmpl:
--------------------------------------------------------------------------------
1 | {
2 | "filter": {
3 | "request_type": "{{ log.type }}"
4 | },
5 |
6 | "content": {
7 | "format": "{{ log.format }}",
8 | "format_string": "{{ log.format_string }}",
9 | "max_request_size": "{{ log.max_request_size }}",
10 | "max_message_size": "{{ log.max_message_size }}"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/templates/v5.1/misc/resolver.tmpl:
--------------------------------------------------------------------------------
1 | # DNS resolver template
2 |
3 | resolver {{ resolverprofile.address }}{% if resolverprofile.valid %}valid={{ resolverprofile.valid }}{% endif %} ipv4={% if resolverprofile.ipv4 == True %}on{% else %}off{% endif %} ipv6={% if resolverprofile.ipv6 == True %}on{% else %}off{% endif %};
4 | {% if resolverprofile.timeout %}resolver_timeout {{ resolverprofile.timeout }}{% endif %};
--------------------------------------------------------------------------------
/templates/v5.1/misc/upstream-http.tmpl:
--------------------------------------------------------------------------------
1 | # HTTP upstream template
2 |
3 | {% if u.name %}
4 | {% if u.origin %}
5 | upstream {{ u.name }} {
6 | zone {{ u.name }} 64k;
7 | {% for o in u.origin -%}
8 | server {{ o.server }}{% if o.weight %} weight={{ o.weight }}{% endif %}{% if o.max_fails %} max_fails={{ o.max_fails }}{% endif %}{% if o.fail_timeout %} fail_timeout={{ o.fail_timeout }}{% endif %}{% if o.max_conns %} max_conns={{ o.max_conns }}{% endif %}{% if o.slow_start %} slow_start={{ o.slow_start }}{% endif %}{% if o.backup and o.backup == True %} backup{% endif %};
9 | {% endfor %}
10 |
11 | {% if u.sticky and u.sticky.cookie and u.sticky.expires and u.sticky.domain and u.sticky.path -%}
12 | sticky cookie {{ u.sticky.cookie }}{% if u.sticky.expires %} expires={{ u.sticky.expires }}{% endif %}{% if u.sticky.domain %} domain={{ u.sticky.domain }}{% endif %}{% if u.sticky.path %} path={{ u.sticky.path }}{% endif %};
13 | {% endif -%}
14 |
15 | {% if u.resolver -%}
16 | include "{{ ncgconfig.nms.resolver_dir }}/{{ u.resolver | replace(" ", "_") }}.conf";
17 | {% endif -%}
18 |
19 | {% if u.snippet and u.snippet.content %}{{ u.snippet.content | b64decode }}{% endif %}
20 |
21 | }
22 | {% endif %}
23 | {% endif %}
--------------------------------------------------------------------------------
/templates/v5.1/misc/upstream-stream.tmpl:
--------------------------------------------------------------------------------
1 | # Stream upstream template
2 |
3 | {% if u.name %}
4 | {% if u.origin %}
5 | upstream {{ u.name }} {
6 | zone {{ u.name }} 64k;
7 | {% for o in u.origin -%}
8 | server {{ o.server }}{% if o.weight %} weight={{ o.weight }}{% endif %}{% if o.max_fails %} max_fails={{ o.max_fails }}{% endif %}{% if o.fail_timeout %} fail_timeout={{ o.fail_timeout }}{% endif %}{% if o.max_conns %} max_conns={{ o.max_conns }}{% endif %}{% if o.slow_start %} slow_start={{ o.slow_start }}{% endif %}{% if o.backup and o.backup == True %} backup{% endif %};
9 | {% endfor %}
10 |
11 | {% if u.snippet and u.snippet.content %}{{ u.snippet.content }}{% endif %}
12 |
13 | {% if u.resolver -%}
14 | include "{{ ncgconfig.nms.resolver_dir }}/{{ u.resolver | replace(" ", "_") }}.conf";
15 | {% endif %}
16 |
17 | }
18 | {% endif %}
19 | {% endif %}
--------------------------------------------------------------------------------
/templates/v5.1/nginx-conf/mime.types:
--------------------------------------------------------------------------------
1 | types {
2 | text/html html htm shtml;
3 | text/css css;
4 | text/xml xml;
5 | image/gif gif;
6 | image/jpeg jpeg jpg;
7 | application/javascript js;
8 | application/atom+xml atom;
9 | application/rss+xml rss;
10 |
11 | text/mathml mml;
12 | text/plain txt;
13 | text/vnd.sun.j2me.app-descriptor jad;
14 | text/vnd.wap.wml wml;
15 | text/x-component htc;
16 |
17 | image/png png;
18 | image/svg+xml svg svgz;
19 | image/tiff tif tiff;
20 | image/vnd.wap.wbmp wbmp;
21 | image/webp webp;
22 | image/x-icon ico;
23 | image/x-jng jng;
24 | image/x-ms-bmp bmp;
25 |
26 | font/woff woff;
27 | font/woff2 woff2;
28 |
29 | application/java-archive jar war ear;
30 | application/json json;
31 | application/mac-binhex40 hqx;
32 | application/msword doc;
33 | application/pdf pdf;
34 | application/postscript ps eps ai;
35 | application/rtf rtf;
36 | application/vnd.apple.mpegurl m3u8;
37 | application/vnd.google-earth.kml+xml kml;
38 | application/vnd.google-earth.kmz kmz;
39 | application/vnd.ms-excel xls;
40 | application/vnd.ms-fontobject eot;
41 | application/vnd.ms-powerpoint ppt;
42 | application/vnd.oasis.opendocument.graphics odg;
43 | application/vnd.oasis.opendocument.presentation odp;
44 | application/vnd.oasis.opendocument.spreadsheet ods;
45 | application/vnd.oasis.opendocument.text odt;
46 | application/vnd.openxmlformats-officedocument.presentationml.presentation
47 | pptx;
48 | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
49 | xlsx;
50 | application/vnd.openxmlformats-officedocument.wordprocessingml.document
51 | docx;
52 | application/vnd.wap.wmlc wmlc;
53 | application/wasm wasm;
54 | application/x-7z-compressed 7z;
55 | application/x-cocoa cco;
56 | application/x-java-archive-diff jardiff;
57 | application/x-java-jnlp-file jnlp;
58 | application/x-makeself run;
59 | application/x-perl pl pm;
60 | application/x-pilot prc pdb;
61 | application/x-rar-compressed rar;
62 | application/x-redhat-package-manager rpm;
63 | application/x-sea sea;
64 | application/x-shockwave-flash swf;
65 | application/x-stuffit sit;
66 | application/x-tcl tcl tk;
67 | application/x-x509-ca-cert der pem crt;
68 | application/x-xpinstall xpi;
69 | application/xhtml+xml xhtml;
70 | application/xspf+xml xspf;
71 | application/zip zip;
72 |
73 | application/octet-stream bin exe dll;
74 | application/octet-stream deb;
75 | application/octet-stream dmg;
76 | application/octet-stream iso img;
77 | application/octet-stream msi msp msm;
78 |
79 | audio/midi mid midi kar;
80 | audio/mpeg mp3;
81 | audio/ogg ogg;
82 | audio/x-m4a m4a;
83 | audio/x-realaudio ra;
84 |
85 | video/3gpp 3gpp 3gp;
86 | video/mp2t ts;
87 | video/mp4 mp4;
88 | video/mpeg mpeg mpg;
89 | video/quicktime mov;
90 | video/webm webm;
91 | video/x-flv flv;
92 | video/x-m4v m4v;
93 | video/x-mng mng;
94 | video/x-ms-asf asx asf;
95 | video/x-ms-wmv wmv;
96 | video/x-msvideo avi;
97 | }
--------------------------------------------------------------------------------
/templates/v5.1/nginx-conf/nginx.conf:
--------------------------------------------------------------------------------
1 | user nginx;
2 | worker_processes auto;
3 |
4 | error_log /var/log/nginx/error.log notice;
5 | pid /var/run/nginx.pid;
6 |
7 | {% for m in nginxconf.modules %}
8 | load_module modules/{{m}}.so;
9 | {% endfor %}
10 |
11 | events {
12 | worker_connections 1024;
13 | }
14 |
15 | http {
16 | include /etc/nginx/mime.types;
17 | default_type application/octet-stream;
18 |
19 | log_format main '$remote_addr - $remote_user [$time_local] "$request" '
20 | '$status $body_bytes_sent "$http_referer" '
21 | '"$http_user_agent" "$http_x_forwarded_for"';
22 |
23 | access_log /var/log/nginx/access.log main;
24 |
25 | sendfile on;
26 | #tcp_nopush on;
27 | keepalive_timeout 65;
28 | #gzip on;
29 | include /etc/nginx/conf.d/*.conf;
30 | }
31 |
32 |
33 | # TCP/UDP proxy and load balancing block
34 | stream {
35 | log_format stream-main '$remote_addr [$time_local] '
36 | '$protocol $status $bytes_sent $bytes_received '
37 | '$session_time "$ssl_preread_server_name"';
38 | #access_log /dev/stdout stream-main;
39 | include /etc/nginx/stream-conf.d/*.conf;
40 | }
--------------------------------------------------------------------------------
/templates/v5.1/stream.tmpl:
--------------------------------------------------------------------------------
1 | # NGINX configuration file - Stream servers - generated by https://github.com/f5devcentral/NGINX-Declarative-API
2 |
3 | {# --- Upstreams section --- #}
4 | {% if declaration.upstreams %}
5 | {% for u in declaration.upstreams %}
6 | {% if u.name %}
7 | include "{{ ncgconfig.nms.upstream_stream_dir }}/{{ u.name | replace(' ', '_') }}.conf";
8 | {% endif %}
9 | {% endfor %}
10 | {% endif %}
11 |
12 | {# --- Stream server section --- #}
13 |
14 | {% for s in declaration.servers %}
15 | {%- if s.listen %}
16 | {% if s.listen.address %}
17 |
18 | server {
19 | listen {{ s.listen.address }}{% if s.listen.protocol == "udp" %} {{ s.listen.protocol }}{% endif %};
20 | status_zone {{ s.name | replace(" ", "_") }};
21 | {% endif -%}
22 | {% endif -%}
23 |
24 | {% if s.resolver -%}
25 | include "{{ ncgconfig.nms.resolver_dir }}/{{ s.resolver | replace(" ", "_") }}.conf";
26 | {% endif -%}
27 |
28 | {# --- TLS section --- #}
29 | {%- if s.listen.tls -%}
30 | {%- if s.listen.tls.certificate -%}
31 | ssl_certificate {{ ncgconfig.nms.certs_dir }}/{{ s.listen.tls.certificate }}.crt;
32 | {% endif -%}
33 | {%- if s.listen.tls.key -%}
34 | ssl_certificate_key {{ ncgconfig.nms.certs_dir }}/{{ s.listen.tls.key }}.key;
35 | {% endif -%}
36 | {% if s.listen.tls.ciphers -%}
37 | ssl_ciphers {{ s.listen.tls.ciphers }};
38 | {% endif -%}
39 | {% if s.listen.tls.protocols -%}
40 | ssl_protocols{% for p in s.listen.tls.protocols %} {{ p }}{% endfor %};
41 | {% endif %}
42 | {% endif %}
43 |
44 | {% if s.upstream -%}
45 | proxy_pass {{ s.upstream }};
46 | {% endif %}
47 |
48 | {% if s.snippet and s.snippet.content %}{{ s.snippet.content | b64decode }}{% endif %}
49 |
50 | {%- if s.listen %}
51 | {%- if s.listen.address %}
52 |
53 | }
54 | {% endif -%}
55 | {% endif -%}
56 |
57 | {%- endfor %}
58 |
--------------------------------------------------------------------------------
/templates/v5.1/visibility/moesif/http.tmpl:
--------------------------------------------------------------------------------
1 | # Moesif integration - https://www.moesif.com/docs/server-integration/nginx-openresty/
2 | # URI: {{ loc.uri }}
3 | # application ID: {{ vis.moesif.application_id }}
4 |
5 | lua_shared_dict moesif_conf 5m;
6 |
7 | init_by_lua_block {
8 | local config = ngx.shared.moesif_conf;
9 | config:set("application_id", "{{ vis.moesif.application_id }}")
10 | }
11 |
12 | lua_package_cpath ";;${prefix}?.so;${prefix}src/?.so;/usr/share/lua/5.1/lua/resty/moesif/?.so;/usr/share/lua/5.1/?.so;/usr/lib64/lua/5.1/?.so;/usr/lib/lua/5.1/?.so;/usr/local/openresty/luajit/share/lua/5.1/lua/resty?.so;/usr/local/share/lua/5.1/resty/moesif/?.so;{{ vis.moesif.plugin_path }}/?.so";
13 | lua_package_path ";;${prefix}?.lua;${prefix}src/?.lua;/usr/share/lua/5.1/lua/resty/moesif/?.lua;/usr/share/lua/5.1/?.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib/lua/5.1/?.lua;/usr/local/openresty/luajit/share/lua/5.1/lua/resty?.lua;/usr/local/share/lua/5.1/resty/moesif/?.lua;{{ vis.moesif.plugin_path }}/?.lua";
14 |
15 |
--------------------------------------------------------------------------------
/templates/v5.1/visibility/moesif/server.tmpl:
--------------------------------------------------------------------------------
1 | # Moesif integration - https://www.moesif.com/docs/server-integration/nginx-openresty/
2 | # URI: {{ loc.uri }}
3 | # application ID: {{ vis.moesif.application_id }}
4 |
5 | # Define the variables Moesif requires
6 | set $moesif_user_id nil;
7 | set $moesif_company_id nil;
8 | set $moesif_req_body nil;
9 | set $moesif_res_body nil;
10 |
11 | # Optionally, set moesif_user_id and moesif_company_id such from a request header or NGINX var to identify customer
12 | header_filter_by_lua_block {
13 | ngx.var.moesif_user_id = ngx.req.get_headers()["X-User-Id"]
14 | ngx.var.moesif_company_id = ngx.req.get_headers()["X-Company-Id"]
15 | }
16 |
17 | # Add Moesif plugin
18 | access_by_lua_file {{ vis.moesif.plugin_path }}/read_req_body.lua;
19 | body_filter_by_lua_file {{ vis.moesif.plugin_path }}/read_res_body.lua;
20 | log_by_lua_file {{ vis.moesif.plugin_path }}/send_event.lua;
21 |
22 |
--------------------------------------------------------------------------------
/templates/v5.2/authn/client/jwks.tmpl:
--------------------------------------------------------------------------------
1 | location = /_auth/jwt/{{ authprofile.name | replace(" ", "_") }}/_jwks_uri {
2 | internal;
3 |
4 | {% if authprofile.jwt.key.startswith('http://') or authprofile.jwt.key.startswith('https://') -%}
5 | proxy_method GET;
6 | proxy_pass {{ authprofile.jwt.key }};
7 | {% else -%}
8 | return 200 '{{ authprofile.jwt.key }}';
9 | {%- endif %}
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/templates/v5.2/authn/client/jwt.tmpl:
--------------------------------------------------------------------------------
1 | auth_jwt "{{ authprofile.jwt.realm }}"{% if authprofile.jwt.token_location %} token={{ authprofile.jwt.token_location }}{% endif %};
2 | auth_jwt_type {{ authprofile.jwt.jwt_type }};
3 | auth_jwt_key_request /_auth/jwt/{{ authprofile.name | replace(" ", "_") }}/_jwks_uri;
4 | {% if authprofile.jwt.cachetime != 0 %}
5 | auth_jwt_key_cache {{ authprofile.jwt.cachetime }};
6 | {% endif %}
7 |
--------------------------------------------------------------------------------
/templates/v5.2/authn/client/mtls.tmpl:
--------------------------------------------------------------------------------
1 | {%- if authprofile.mtls.enabled|lower != "off" -%}
2 | ssl_verify_client {{ authprofile.mtls.enabled }};
3 | {% if authprofile.mtls.client_certificates -%}
4 | ssl_client_certificate {{ ncgconfig.nms.certs_dir }}/{{ authprofile.mtls.client_certificates }}.crt;
5 | {% endif %}
6 |
7 | {% if authprofile.mtls.trusted_ca_certificates -%}
8 | ssl_trusted_certificate {{ ncgconfig.nms.certs_dir }}/{{ authprofile.mtls.trusted_ca_certificates }}.crt;
9 | {% endif %}
10 |
11 | {# --- OCSP section start --- #}
12 | {%- if authprofile.mtls.ocsp and authprofile.mtls.ocsp.enabled|lower != "off" -%}
13 | ssl_ocsp {{ authprofile.mtls.ocsp.enabled }};
14 | {% if authprofile.mtls.ocsp.responder -%}
15 | ssl_ocsp_responder {{ authprofile.mtls.ocsp.responder }};
16 | {% endif %}
17 | {% endif %}
18 | {# --- OCSP section end --- #}
19 |
20 | {# --- TLS stapling section start --- #}
21 | {%- if authprofile.mtls.stapling and authprofile.mtls.stapling.enabled == True -%}
22 | ssl_stapling on;
23 | ssl_stapling_verify {% if authprofile.mtls.stapling.verify == True %}on{% else %}off{% endif %};
24 | {% if authprofile.mtls.stapling.responder -%}
25 | ssl_stapling_responder {{ authprofile.mtls.stapling.responder }};
26 | {% endif -%}
27 | {%- endif %}
28 | {# --- TLS stapling section end --- #}
29 | {% endif %}
--------------------------------------------------------------------------------
/templates/v5.2/authn/server/mtls.tmpl:
--------------------------------------------------------------------------------
1 | proxy_ssl_certificate {{ ncgconfig.nms.certs_dir }}/{{ authprofile.mtls.certificate }}.crt;
2 | proxy_ssl_certificate_key {{ ncgconfig.nms.certs_dir }}/{{ authprofile.mtls.certificate }}.key;
3 |
--------------------------------------------------------------------------------
/templates/v5.2/authn/server/token.tmpl:
--------------------------------------------------------------------------------
1 | {% if authprofile.token.type == "bearer" %}
2 | proxy_set_header Authorization "Bearer {{ authprofile.token.token }}";
3 | {% elif authprofile.token.type == "basic" %}
4 | proxy_set_header Authorization "Basic {{ (authprofile.token.username + ':' + (authprofile.token.password | b64decode) ) | b64encode }}";
5 | {% elif authprofile.token.type == "header" %}
6 | proxy_set_header {{ authprofile.token.location }} "{{ authprofile.token.token }}";
7 | {% endif %}
--------------------------------------------------------------------------------
/templates/v5.2/authz/client/jwt-authz-map.tmpl:
--------------------------------------------------------------------------------
1 | {% for claim in authprofile.jwt.claims %}
2 | auth_jwt_claim_set $authz_match_jwt_claim_{{ claim.name }}_{{ authprofile.name | replace(" ", "_") }} {{ claim.name }};
3 | {% endfor %}
4 |
5 | {% for claim in authprofile.jwt.claims %}
6 | # JWT claim {{ claim.name }} validation for profile "{{ authprofile.name }}"
7 | map $authz_match_jwt_claim_{{ claim.name }}_{{ authprofile.name | replace(" ", "_") }} $jwt_authz_claim_{{ claim.name }}_{{ authprofile.name | replace(" ", "_") }} {
8 | {% for value in claim.value %}
9 | "{{ value }}" 1;
10 | {% endfor %}
11 | default 0;
12 | }
13 |
14 | {% endfor %}
--------------------------------------------------------------------------------
/templates/v5.2/authz/client/jwt.tmpl:
--------------------------------------------------------------------------------
1 | {% for claim in authprofile.jwt.claims %}
2 | auth_jwt_require $jwt_authz_claim_{{ claim.name }}_{{ authprofile.name | replace(" ", "_") }} error={{ claim.errorcode }};
3 | {% endfor %}
--------------------------------------------------------------------------------
/templates/v5.2/devportal/backstage.tmpl:
--------------------------------------------------------------------------------
1 | apiVersion: backstage.io/v1alpha1
2 | kind: API
3 | metadata:
4 | name: {{ declaration.name }}
5 | annotations:
6 | github.com/project-slug: backstage/backstage
7 | backstage.io/techdocs-ref: dir:.
8 | lighthouse.com/website-url: https://backstage.io
9 | spec:
10 | type: openapi
11 | lifecycle: {{ declaration.lifecycle }}
12 | owner: {{ declaration.owner }}
13 | system: {{ declaration.system }}
14 | definition: |
15 | {% filter indent(width=4) %}
16 | {{ openAPISchema }}
17 | {% endfilter %}
--------------------------------------------------------------------------------
/templates/v5.2/logformat.tmpl:
--------------------------------------------------------------------------------
1 | {
2 | "filter": {
3 | "request_type": "{{ log.type }}"
4 | },
5 |
6 | "content": {
7 | "format": "{{ log.format }}",
8 | "format_string": "{{ log.format_string }}",
9 | "max_request_size": "{{ log.max_request_size }}",
10 | "max_message_size": "{{ log.max_message_size }}"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/templates/v5.2/misc/resolver.tmpl:
--------------------------------------------------------------------------------
1 | # DNS resolver template
2 |
3 | resolver {{ resolverprofile.address }}{% if resolverprofile.valid %}valid={{ resolverprofile.valid }}{% endif %} ipv4={% if resolverprofile.ipv4 == True %}on{% else %}off{% endif %} ipv6={% if resolverprofile.ipv6 == True %}on{% else %}off{% endif %};
4 | {% if resolverprofile.timeout %}resolver_timeout {{ resolverprofile.timeout }}{% endif %};
--------------------------------------------------------------------------------
/templates/v5.2/misc/upstream-http.tmpl:
--------------------------------------------------------------------------------
1 | # HTTP upstream template
2 |
3 | {% if u.name %}
4 | {% if u.origin %}
5 | upstream {{ u.name }} {
6 | zone {{ u.name }} 64k;
7 | {% for o in u.origin -%}
8 | server {{ o.server }}{% if o.weight %} weight={{ o.weight }}{% endif %}{% if o.max_fails %} max_fails={{ o.max_fails }}{% endif %}{% if o.fail_timeout %} fail_timeout={{ o.fail_timeout }}{% endif %}{% if o.max_conns %} max_conns={{ o.max_conns }}{% endif %}{% if o.slow_start %} slow_start={{ o.slow_start }}{% endif %}{% if o.backup and o.backup == True %} backup{% endif %};
9 | {% endfor %}
10 |
11 | {% if u.sticky and u.sticky.cookie and u.sticky.expires and u.sticky.domain and u.sticky.path -%}
12 | sticky cookie {{ u.sticky.cookie }}{% if u.sticky.expires %} expires={{ u.sticky.expires }}{% endif %}{% if u.sticky.domain %} domain={{ u.sticky.domain }}{% endif %}{% if u.sticky.path %} path={{ u.sticky.path }}{% endif %};
13 | {% endif -%}
14 |
15 | {% if u.resolver -%}
16 | include "{{ ncgconfig.nms.resolver_dir }}/{{ u.resolver | replace(" ", "_") }}.conf";
17 | {% endif -%}
18 |
19 | {% if u.snippet and u.snippet.content %}{{ u.snippet.content | b64decode }}{% endif %}
20 |
21 | }
22 | {% endif %}
23 | {% endif %}
--------------------------------------------------------------------------------
/templates/v5.2/misc/upstream-stream.tmpl:
--------------------------------------------------------------------------------
1 | # Stream upstream template
2 |
3 | {% if u.name %}
4 | {% if u.origin %}
5 | upstream {{ u.name }} {
6 | zone {{ u.name }} 64k;
7 | {% for o in u.origin -%}
8 | server {{ o.server }}{% if o.weight %} weight={{ o.weight }}{% endif %}{% if o.max_fails %} max_fails={{ o.max_fails }}{% endif %}{% if o.fail_timeout %} fail_timeout={{ o.fail_timeout }}{% endif %}{% if o.max_conns %} max_conns={{ o.max_conns }}{% endif %}{% if o.slow_start %} slow_start={{ o.slow_start }}{% endif %}{% if o.backup and o.backup == True %} backup{% endif %};
9 | {% endfor %}
10 |
11 | {% if u.snippet and u.snippet.content %}{{ u.snippet.content }}{% endif %}
12 |
13 | {% if u.resolver -%}
14 | include "{{ ncgconfig.nms.resolver_dir }}/{{ u.resolver | replace(" ", "_") }}.conf";
15 | {% endif %}
16 |
17 | }
18 | {% endif %}
19 | {% endif %}
--------------------------------------------------------------------------------
/templates/v5.2/nginx-conf/license-key.tmpl:
--------------------------------------------------------------------------------
1 | {{ nginxconf.license.token }}
--------------------------------------------------------------------------------
/templates/v5.2/nginx-conf/mime.types:
--------------------------------------------------------------------------------
1 | types {
2 | text/html html htm shtml;
3 | text/css css;
4 | text/xml xml;
5 | image/gif gif;
6 | image/jpeg jpeg jpg;
7 | application/javascript js;
8 | application/atom+xml atom;
9 | application/rss+xml rss;
10 |
11 | text/mathml mml;
12 | text/plain txt;
13 | text/vnd.sun.j2me.app-descriptor jad;
14 | text/vnd.wap.wml wml;
15 | text/x-component htc;
16 |
17 | image/png png;
18 | image/svg+xml svg svgz;
19 | image/tiff tif tiff;
20 | image/vnd.wap.wbmp wbmp;
21 | image/webp webp;
22 | image/x-icon ico;
23 | image/x-jng jng;
24 | image/x-ms-bmp bmp;
25 |
26 | font/woff woff;
27 | font/woff2 woff2;
28 |
29 | application/java-archive jar war ear;
30 | application/json json;
31 | application/mac-binhex40 hqx;
32 | application/msword doc;
33 | application/pdf pdf;
34 | application/postscript ps eps ai;
35 | application/rtf rtf;
36 | application/vnd.apple.mpegurl m3u8;
37 | application/vnd.google-earth.kml+xml kml;
38 | application/vnd.google-earth.kmz kmz;
39 | application/vnd.ms-excel xls;
40 | application/vnd.ms-fontobject eot;
41 | application/vnd.ms-powerpoint ppt;
42 | application/vnd.oasis.opendocument.graphics odg;
43 | application/vnd.oasis.opendocument.presentation odp;
44 | application/vnd.oasis.opendocument.spreadsheet ods;
45 | application/vnd.oasis.opendocument.text odt;
46 | application/vnd.openxmlformats-officedocument.presentationml.presentation
47 | pptx;
48 | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
49 | xlsx;
50 | application/vnd.openxmlformats-officedocument.wordprocessingml.document
51 | docx;
52 | application/vnd.wap.wmlc wmlc;
53 | application/wasm wasm;
54 | application/x-7z-compressed 7z;
55 | application/x-cocoa cco;
56 | application/x-java-archive-diff jardiff;
57 | application/x-java-jnlp-file jnlp;
58 | application/x-makeself run;
59 | application/x-perl pl pm;
60 | application/x-pilot prc pdb;
61 | application/x-rar-compressed rar;
62 | application/x-redhat-package-manager rpm;
63 | application/x-sea sea;
64 | application/x-shockwave-flash swf;
65 | application/x-stuffit sit;
66 | application/x-tcl tcl tk;
67 | application/x-x509-ca-cert der pem crt;
68 | application/x-xpinstall xpi;
69 | application/xhtml+xml xhtml;
70 | application/xspf+xml xspf;
71 | application/zip zip;
72 |
73 | application/octet-stream bin exe dll;
74 | application/octet-stream deb;
75 | application/octet-stream dmg;
76 | application/octet-stream iso img;
77 | application/octet-stream msi msp msm;
78 |
79 | audio/midi mid midi kar;
80 | audio/mpeg mp3;
81 | audio/ogg ogg;
82 | audio/x-m4a m4a;
83 | audio/x-realaudio ra;
84 |
85 | video/3gpp 3gpp 3gp;
86 | video/mp2t ts;
87 | video/mp4 mp4;
88 | video/mpeg mpeg mpg;
89 | video/quicktime mov;
90 | video/webm webm;
91 | video/x-flv flv;
92 | video/x-m4v m4v;
93 | video/x-mng mng;
94 | video/x-ms-asf asx asf;
95 | video/x-ms-wmv wmv;
96 | video/x-msvideo avi;
97 | }
--------------------------------------------------------------------------------
/templates/v5.2/nginx-conf/nginx.conf:
--------------------------------------------------------------------------------
1 | user nginx;
2 | worker_processes auto;
3 |
4 | error_log /var/log/nginx/error.log notice;
5 | pid /var/run/nginx.pid;
6 |
7 | {% for m in nginxconf.modules %}
8 | load_module modules/{{m}}.so;
9 | {% endfor %}
10 |
11 | events {
12 | worker_connections 1024;
13 | }
14 |
15 | http {
16 | include /etc/nginx/mime.types;
17 | default_type application/octet-stream;
18 |
19 | log_format main '$remote_addr - $remote_user [$time_local] "$request" '
20 | '$status $body_bytes_sent "$http_referer" '
21 | '"$http_user_agent" "$http_x_forwarded_for"';
22 |
23 | access_log /var/log/nginx/access.log main;
24 |
25 | sendfile on;
26 | #tcp_nopush on;
27 | keepalive_timeout 65;
28 | #gzip on;
29 | include /etc/nginx/conf.d/*.conf;
30 | }
31 |
32 | # TCP/UDP proxy and load balancing block
33 | stream {
34 | log_format stream-main '$remote_addr [$time_local] '
35 | '$protocol $status $bytes_sent $bytes_received '
36 | '$session_time "$ssl_preread_server_name"';
37 | #access_log /dev/stdout stream-main;
38 | include /etc/nginx/stream-conf.d/*.conf;
39 | }
40 |
41 | {% if nginxconf.license %}
42 | # NGINX R33+ license
43 | mgmt {
44 | # Default reporting sent to product.connect.nginx.com
45 | usage_report endpoint={{ nginxconf.license.endpoint }};
46 | license_token /etc/nginx/license.jwt;
47 |
48 | # Set to 'off' to begin the 180-day reporting enforcement grace period.
49 | # Reporting must begin or resume before the end of the grace period
50 | # to ensure continued operation.
51 | enforce_initial_report {% if nginxconf.license.grace_period == False %}on{% else %}off{% endif %};
52 |
53 | # Set to 'off' to trust all SSL certificates (not recommended).
54 | # Useful for reporting to NGINX Instance Manager without a local PKI.
55 | ssl_verify {% if nginxconf.license.ssl_verify == True %}on{% else %}off{% endif %};
56 | }
57 | {% endif %}
--------------------------------------------------------------------------------
/templates/v5.2/stream.tmpl:
--------------------------------------------------------------------------------
1 | # NGINX configuration file - Stream servers - generated by https://github.com/f5devcentral/NGINX-Declarative-API
2 |
3 | {# --- Upstreams section --- #}
4 | {% if declaration.upstreams %}
5 | {% for u in declaration.upstreams %}
6 | {% if u.name %}
7 | include "{{ ncgconfig.nms.upstream_stream_dir }}/{{ u.name | replace(' ', '_') }}.conf";
8 | {% endif %}
9 | {% endfor %}
10 | {% endif %}
11 |
12 | {# --- Stream server section --- #}
13 |
14 | {% for s in declaration.servers %}
15 | {%- if s.listen %}
16 | {% if s.listen.address %}
17 |
18 | server {
19 | listen {{ s.listen.address }}{% if s.listen.protocol == "udp" %} {{ s.listen.protocol }}{% endif %};
20 | status_zone {{ s.name | replace(" ", "_") }};
21 | {% endif -%}
22 | {% endif -%}
23 |
24 | {% if s.resolver -%}
25 | include "{{ ncgconfig.nms.resolver_dir }}/{{ s.resolver | replace(" ", "_") }}.conf";
26 | {% endif -%}
27 |
28 | {# --- TLS section --- #}
29 | {%- if s.listen.tls -%}
30 | {%- if s.listen.tls.certificate -%}
31 | ssl_certificate {{ ncgconfig.nms.certs_dir }}/{{ s.listen.tls.certificate }}.crt;
32 | {% endif -%}
33 | {%- if s.listen.tls.key -%}
34 | ssl_certificate_key {{ ncgconfig.nms.certs_dir }}/{{ s.listen.tls.key }}.key;
35 | {% endif -%}
36 | {% if s.listen.tls.ciphers -%}
37 | ssl_ciphers {{ s.listen.tls.ciphers }};
38 | {% endif -%}
39 | {% if s.listen.tls.protocols -%}
40 | ssl_protocols{% for p in s.listen.tls.protocols %} {{ p }}{% endfor %};
41 | {% endif %}
42 | {% endif %}
43 |
44 | {% if s.upstream -%}
45 | proxy_pass {{ s.upstream }};
46 | {% endif %}
47 |
48 | {% if s.snippet and s.snippet.content %}{{ s.snippet.content | b64decode }}{% endif %}
49 |
50 | {%- if s.listen %}
51 | {%- if s.listen.address %}
52 |
53 | }
54 | {% endif -%}
55 | {% endif -%}
56 |
57 | {%- endfor %}
58 |
--------------------------------------------------------------------------------
/templates/v5.2/visibility/moesif/http.tmpl:
--------------------------------------------------------------------------------
1 | # Moesif integration - https://www.moesif.com/docs/server-integration/nginx-openresty/
2 | # URI: {{ loc.uri }}
3 | # application ID: {{ vis.moesif.application_id }}
4 |
5 | lua_shared_dict moesif_conf 5m;
6 |
7 | init_by_lua_block {
8 | local config = ngx.shared.moesif_conf;
9 | config:set("application_id", "{{ vis.moesif.application_id }}")
10 | }
11 |
12 | lua_package_cpath ";;${prefix}?.so;${prefix}src/?.so;/usr/share/lua/5.1/lua/resty/moesif/?.so;/usr/share/lua/5.1/?.so;/usr/lib64/lua/5.1/?.so;/usr/lib/lua/5.1/?.so;/usr/local/openresty/luajit/share/lua/5.1/lua/resty?.so;/usr/local/share/lua/5.1/resty/moesif/?.so;{{ vis.moesif.plugin_path }}/?.so";
13 | lua_package_path ";;${prefix}?.lua;${prefix}src/?.lua;/usr/share/lua/5.1/lua/resty/moesif/?.lua;/usr/share/lua/5.1/?.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib/lua/5.1/?.lua;/usr/local/openresty/luajit/share/lua/5.1/lua/resty?.lua;/usr/local/share/lua/5.1/resty/moesif/?.lua;{{ vis.moesif.plugin_path }}/?.lua";
14 |
15 |
--------------------------------------------------------------------------------
/templates/v5.2/visibility/moesif/server.tmpl:
--------------------------------------------------------------------------------
1 | # Moesif integration - https://www.moesif.com/docs/server-integration/nginx-openresty/
2 | # URI: {{ loc.uri }}
3 | # application ID: {{ vis.moesif.application_id }}
4 |
5 | # Define the variables Moesif requires
6 | set $moesif_user_id nil;
7 | set $moesif_company_id nil;
8 | set $moesif_req_body nil;
9 | set $moesif_res_body nil;
10 |
11 | # Optionally, set moesif_user_id and moesif_company_id such from a request header or NGINX var to identify customer
12 | header_filter_by_lua_block {
13 | ngx.var.moesif_user_id = ngx.req.get_headers()["X-User-Id"]
14 | ngx.var.moesif_company_id = ngx.req.get_headers()["X-Company-Id"]
15 | }
16 |
17 | # Add Moesif plugin
18 | access_by_lua_file {{ vis.moesif.plugin_path }}/read_req_body.lua;
19 | body_filter_by_lua_file {{ vis.moesif.plugin_path }}/read_res_body.lua;
20 | log_by_lua_file {{ vis.moesif.plugin_path }}/send_event.lua;
21 |
22 |
--------------------------------------------------------------------------------
/templates/v5.3/authn/client/jwks.tmpl:
--------------------------------------------------------------------------------
1 | location = /_auth/jwt/{{ authprofile.name | replace(" ", "_") }}/_jwks_uri {
2 | internal;
3 |
4 | {% if authprofile.jwt.key.startswith('http://') or authprofile.jwt.key.startswith('https://') -%}
5 | proxy_method GET;
6 | proxy_pass {{ authprofile.jwt.key }};
7 | {% else -%}
8 | return 200 '{{ authprofile.jwt.key }}';
9 | {%- endif %}
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/templates/v5.3/authn/client/jwt.tmpl:
--------------------------------------------------------------------------------
1 | auth_jwt "{{ authprofile.jwt.realm }}"{% if authprofile.jwt.token_location %} token={{ authprofile.jwt.token_location }}{% endif %};
2 | auth_jwt_type {{ authprofile.jwt.jwt_type }};
3 | auth_jwt_key_request /_auth/jwt/{{ authprofile.name | replace(" ", "_") }}/_jwks_uri;
4 | {% if authprofile.jwt.cachetime != 0 %}
5 | auth_jwt_key_cache {{ authprofile.jwt.cachetime }};
6 | {% endif %}
7 |
--------------------------------------------------------------------------------
/templates/v5.3/authn/client/mtls.tmpl:
--------------------------------------------------------------------------------
1 | {%- if authprofile.mtls.enabled|lower != "off" -%}
2 | ssl_verify_client {{ authprofile.mtls.enabled }};
3 | {% if authprofile.mtls.client_certificates -%}
4 | ssl_client_certificate {{ ncgconfig.nms.certs_dir }}/{{ authprofile.mtls.client_certificates }}.crt;
5 | {% endif %}
6 |
7 | {% if authprofile.mtls.trusted_ca_certificates -%}
8 | ssl_trusted_certificate {{ ncgconfig.nms.certs_dir }}/{{ authprofile.mtls.trusted_ca_certificates }}.crt;
9 | {% endif %}
10 |
11 | {# --- OCSP section start --- #}
12 | {%- if authprofile.mtls.ocsp and authprofile.mtls.ocsp.enabled|lower != "off" -%}
13 | ssl_ocsp {{ authprofile.mtls.ocsp.enabled }};
14 | {% if authprofile.mtls.ocsp.responder -%}
15 | ssl_ocsp_responder {{ authprofile.mtls.ocsp.responder }};
16 | {% endif %}
17 | {% endif %}
18 | {# --- OCSP section end --- #}
19 |
20 | {# --- TLS stapling section start --- #}
21 | {%- if authprofile.mtls.stapling and authprofile.mtls.stapling.enabled == True -%}
22 | ssl_stapling on;
23 | ssl_stapling_verify {% if authprofile.mtls.stapling.verify == True %}on{% else %}off{% endif %};
24 | {% if authprofile.mtls.stapling.responder -%}
25 | ssl_stapling_responder {{ authprofile.mtls.stapling.responder }};
26 | {% endif -%}
27 | {%- endif %}
28 | {# --- TLS stapling section end --- #}
29 | {% endif %}
--------------------------------------------------------------------------------
/templates/v5.3/authn/server/mtls.tmpl:
--------------------------------------------------------------------------------
1 | proxy_ssl_certificate {{ ncgconfig.nms.certs_dir }}/{{ authprofile.mtls.certificate }}.crt;
2 | proxy_ssl_certificate_key {{ ncgconfig.nms.certs_dir }}/{{ authprofile.mtls.certificate }}.key;
3 |
--------------------------------------------------------------------------------
/templates/v5.3/authn/server/token.tmpl:
--------------------------------------------------------------------------------
1 | {% if authprofile.token.type == "bearer" %}
2 | proxy_set_header Authorization "Bearer {{ authprofile.token.token }}";
3 | {% elif authprofile.token.type == "basic" %}
4 | proxy_set_header Authorization "Basic {{ (authprofile.token.username + ':' + (authprofile.token.password | b64decode) ) | b64encode }}";
5 | {% elif authprofile.token.type == "header" %}
6 | proxy_set_header {{ authprofile.token.location }} "{{ authprofile.token.token }}";
7 | {% endif %}
--------------------------------------------------------------------------------
/templates/v5.3/authz/client/jwt-authz-map.tmpl:
--------------------------------------------------------------------------------
1 | {% for claim in authprofile.jwt.claims %}
2 | auth_jwt_claim_set $authz_match_jwt_claim_{{ claim.name }}_{{ authprofile.name | replace(" ", "_") }} {{ claim.name }};
3 | {% endfor %}
4 |
5 | {% for claim in authprofile.jwt.claims %}
6 | # JWT claim {{ claim.name }} validation for profile "{{ authprofile.name }}"
7 | map $authz_match_jwt_claim_{{ claim.name }}_{{ authprofile.name | replace(" ", "_") }} $jwt_authz_claim_{{ claim.name }}_{{ authprofile.name | replace(" ", "_") }} {
8 | {% for value in claim.value %}
9 | "{{ value }}" 1;
10 | {% endfor %}
11 | default 0;
12 | }
13 |
14 | {% endfor %}
--------------------------------------------------------------------------------
/templates/v5.3/authz/client/jwt.tmpl:
--------------------------------------------------------------------------------
1 | {% for claim in authprofile.jwt.claims %}
2 | auth_jwt_require $jwt_authz_claim_{{ claim.name }}_{{ authprofile.name | replace(" ", "_") }} error={{ claim.errorcode }};
3 | {% endfor %}
--------------------------------------------------------------------------------
/templates/v5.3/devportal/backstage.tmpl:
--------------------------------------------------------------------------------
1 | apiVersion: backstage.io/v1alpha1
2 | kind: API
3 | metadata:
4 | name: {{ declaration.name }}
5 | annotations:
6 | github.com/project-slug: backstage/backstage
7 | backstage.io/techdocs-ref: dir:.
8 | lighthouse.com/website-url: https://backstage.io
9 | spec:
10 | type: openapi
11 | lifecycle: {{ declaration.lifecycle }}
12 | owner: {{ declaration.owner }}
13 | system: {{ declaration.system }}
14 | definition: |
15 | {% filter indent(width=4) %}
16 | {{ openAPISchema }}
17 | {% endfilter %}
--------------------------------------------------------------------------------
/templates/v5.3/logformat.tmpl:
--------------------------------------------------------------------------------
1 | {
2 | "filter": {
3 | "request_type": "{{ log.type }}"
4 | },
5 |
6 | "content": {
7 | "format": "{{ log.format }}",
8 | "format_string": "{{ log.format_string }}",
9 | "max_request_size": "{{ log.max_request_size }}",
10 | "max_message_size": "{{ log.max_message_size }}"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/templates/v5.3/misc/resolver.tmpl:
--------------------------------------------------------------------------------
1 | # DNS resolver template
2 |
3 | resolver {{ resolverprofile.address }}{% if resolverprofile.valid %}valid={{ resolverprofile.valid }}{% endif %} ipv4={% if resolverprofile.ipv4 == True %}on{% else %}off{% endif %} ipv6={% if resolverprofile.ipv6 == True %}on{% else %}off{% endif %};
4 | {% if resolverprofile.timeout %}resolver_timeout {{ resolverprofile.timeout }}{% endif %};
--------------------------------------------------------------------------------
/templates/v5.3/misc/upstream-http.tmpl:
--------------------------------------------------------------------------------
1 | # HTTP upstream template
2 |
3 | {% if u.name %}
4 | {% if u.origin %}
5 | upstream {{ u.name }} {
6 | zone {{ u.name }} 64k;
7 | {% for o in u.origin -%}
8 | server {{ o.server }}{% if o.weight %} weight={{ o.weight }}{% endif %}{% if o.max_fails %} max_fails={{ o.max_fails }}{% endif %}{% if o.fail_timeout %} fail_timeout={{ o.fail_timeout }}{% endif %}{% if o.max_conns %} max_conns={{ o.max_conns }}{% endif %}{% if o.slow_start %} slow_start={{ o.slow_start }}{% endif %}{% if o.backup and o.backup == True %} backup{% endif %};
9 | {% endfor %}
10 |
11 | {% if u.sticky and u.sticky.cookie and u.sticky.expires and u.sticky.domain and u.sticky.path -%}
12 | sticky cookie {{ u.sticky.cookie }}{% if u.sticky.expires %} expires={{ u.sticky.expires }}{% endif %}{% if u.sticky.domain %} domain={{ u.sticky.domain }}{% endif %}{% if u.sticky.path %} path={{ u.sticky.path }}{% endif %};
13 | {% endif -%}
14 |
15 | {% if u.resolver -%}
16 | include "{{ ncgconfig.nms.resolver_dir }}/{{ u.resolver | replace(" ", "_") }}.conf";
17 | {% endif -%}
18 |
19 | {% if u.snippet and u.snippet.content %}{{ u.snippet.content | b64decode }}{% endif %}
20 |
21 | }
22 | {% endif %}
23 | {% endif %}
--------------------------------------------------------------------------------
/templates/v5.3/misc/upstream-stream.tmpl:
--------------------------------------------------------------------------------
1 | # Stream upstream template
2 |
3 | {% if u.name %}
4 | {% if u.origin %}
5 | upstream {{ u.name }} {
6 | zone {{ u.name }} 64k;
7 | {% for o in u.origin -%}
8 | server {{ o.server }}{% if o.weight %} weight={{ o.weight }}{% endif %}{% if o.max_fails %} max_fails={{ o.max_fails }}{% endif %}{% if o.fail_timeout %} fail_timeout={{ o.fail_timeout }}{% endif %}{% if o.max_conns %} max_conns={{ o.max_conns }}{% endif %}{% if o.slow_start %} slow_start={{ o.slow_start }}{% endif %}{% if o.backup and o.backup == True %} backup{% endif %};
9 | {% endfor %}
10 |
11 | {% if u.snippet and u.snippet.content %}{{ u.snippet.content }}{% endif %}
12 |
13 | {% if u.resolver -%}
14 | include "{{ ncgconfig.nms.resolver_dir }}/{{ u.resolver | replace(" ", "_") }}.conf";
15 | {% endif %}
16 |
17 | }
18 | {% endif %}
19 | {% endif %}
--------------------------------------------------------------------------------
/templates/v5.3/nginx-conf/license-key.tmpl:
--------------------------------------------------------------------------------
1 | {{ nginxconf.license.token }}
--------------------------------------------------------------------------------
/templates/v5.3/nginx-conf/mime.types:
--------------------------------------------------------------------------------
1 | types {
2 | text/html html htm shtml;
3 | text/css css;
4 | text/xml xml;
5 | image/gif gif;
6 | image/jpeg jpeg jpg;
7 | application/javascript js;
8 | application/atom+xml atom;
9 | application/rss+xml rss;
10 |
11 | text/mathml mml;
12 | text/plain txt;
13 | text/vnd.sun.j2me.app-descriptor jad;
14 | text/vnd.wap.wml wml;
15 | text/x-component htc;
16 |
17 | image/png png;
18 | image/svg+xml svg svgz;
19 | image/tiff tif tiff;
20 | image/vnd.wap.wbmp wbmp;
21 | image/webp webp;
22 | image/x-icon ico;
23 | image/x-jng jng;
24 | image/x-ms-bmp bmp;
25 |
26 | font/woff woff;
27 | font/woff2 woff2;
28 |
29 | application/java-archive jar war ear;
30 | application/json json;
31 | application/mac-binhex40 hqx;
32 | application/msword doc;
33 | application/pdf pdf;
34 | application/postscript ps eps ai;
35 | application/rtf rtf;
36 | application/vnd.apple.mpegurl m3u8;
37 | application/vnd.google-earth.kml+xml kml;
38 | application/vnd.google-earth.kmz kmz;
39 | application/vnd.ms-excel xls;
40 | application/vnd.ms-fontobject eot;
41 | application/vnd.ms-powerpoint ppt;
42 | application/vnd.oasis.opendocument.graphics odg;
43 | application/vnd.oasis.opendocument.presentation odp;
44 | application/vnd.oasis.opendocument.spreadsheet ods;
45 | application/vnd.oasis.opendocument.text odt;
46 | application/vnd.openxmlformats-officedocument.presentationml.presentation
47 | pptx;
48 | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
49 | xlsx;
50 | application/vnd.openxmlformats-officedocument.wordprocessingml.document
51 | docx;
52 | application/vnd.wap.wmlc wmlc;
53 | application/wasm wasm;
54 | application/x-7z-compressed 7z;
55 | application/x-cocoa cco;
56 | application/x-java-archive-diff jardiff;
57 | application/x-java-jnlp-file jnlp;
58 | application/x-makeself run;
59 | application/x-perl pl pm;
60 | application/x-pilot prc pdb;
61 | application/x-rar-compressed rar;
62 | application/x-redhat-package-manager rpm;
63 | application/x-sea sea;
64 | application/x-shockwave-flash swf;
65 | application/x-stuffit sit;
66 | application/x-tcl tcl tk;
67 | application/x-x509-ca-cert der pem crt;
68 | application/x-xpinstall xpi;
69 | application/xhtml+xml xhtml;
70 | application/xspf+xml xspf;
71 | application/zip zip;
72 |
73 | application/octet-stream bin exe dll;
74 | application/octet-stream deb;
75 | application/octet-stream dmg;
76 | application/octet-stream iso img;
77 | application/octet-stream msi msp msm;
78 |
79 | audio/midi mid midi kar;
80 | audio/mpeg mp3;
81 | audio/ogg ogg;
82 | audio/x-m4a m4a;
83 | audio/x-realaudio ra;
84 |
85 | video/3gpp 3gpp 3gp;
86 | video/mp2t ts;
87 | video/mp4 mp4;
88 | video/mpeg mpeg mpg;
89 | video/quicktime mov;
90 | video/webm webm;
91 | video/x-flv flv;
92 | video/x-m4v m4v;
93 | video/x-mng mng;
94 | video/x-ms-asf asx asf;
95 | video/x-ms-wmv wmv;
96 | video/x-msvideo avi;
97 | }
--------------------------------------------------------------------------------
/templates/v5.3/nginx-conf/nginx.conf:
--------------------------------------------------------------------------------
1 | user nginx;
2 | worker_processes auto;
3 |
4 | error_log /var/log/nginx/error.log notice;
5 | pid /var/run/nginx.pid;
6 |
7 | {% for m in nginxconf.modules %}
8 | load_module modules/{{m}}.so;
9 | {% endfor %}
10 |
11 | events {
12 | worker_connections 1024;
13 | }
14 |
15 | http {
16 | include /etc/nginx/mime.types;
17 | default_type application/octet-stream;
18 |
19 | log_format main '$remote_addr - $remote_user [$time_local] "$request" '
20 | '$status $body_bytes_sent "$http_referer" '
21 | '"$http_user_agent" "$http_x_forwarded_for"';
22 |
23 | access_log /var/log/nginx/access.log main;
24 |
25 | sendfile on;
26 | #tcp_nopush on;
27 | keepalive_timeout 65;
28 | #gzip on;
29 | include /etc/nginx/conf.d/*.conf;
30 | }
31 |
32 | # TCP/UDP proxy and load balancing block
33 | stream {
34 | log_format stream-main '$remote_addr [$time_local] '
35 | '$protocol $status $bytes_sent $bytes_received '
36 | '$session_time "$ssl_preread_server_name"';
37 | #access_log /dev/stdout stream-main;
38 | include /etc/nginx/stream-conf.d/*.conf;
39 | }
40 |
41 | {% if nginxconf.license %}
42 | # NGINX R33+ license
43 | mgmt {
44 | # Default reporting sent to product.connect.nginx.com
45 | usage_report endpoint={{ nginxconf.license.endpoint }};
46 | license_token /etc/nginx/license.jwt;
47 |
48 | # Set to 'off' to begin the 180-day reporting enforcement grace period.
49 | # Reporting must begin or resume before the end of the grace period
50 | # to ensure continued operation.
51 | enforce_initial_report {% if nginxconf.license.grace_period == False %}on{% else %}off{% endif %};
52 |
53 | # Set to 'off' to trust all SSL certificates (not recommended).
54 | # Useful for reporting to NGINX Instance Manager without a local PKI.
55 | ssl_verify {% if nginxconf.license.ssl_verify == True %}on{% else %}off{% endif %};
56 | }
57 | {% endif %}
--------------------------------------------------------------------------------
/templates/v5.3/stream.tmpl:
--------------------------------------------------------------------------------
1 | # NGINX configuration file - Stream servers - generated by https://github.com/f5devcentral/NGINX-Declarative-API
2 |
3 | {# --- Upstreams section --- #}
4 | {% if declaration.upstreams %}
5 | # Upstreams
6 | {% for u in declaration.upstreams %}
7 | {% if u.name %}
8 | include "{{ ncgconfig.nms.upstream_stream_dir }}/{{ u.name | replace(' ', '_') }}.conf";
9 | {% endif %}
10 | {% endfor %}
11 | {% endif %}
12 |
13 | {# --- Stream server section --- #}
14 |
15 | {% for s in declaration.servers %}
16 | {%- if s.listen %}
17 | {% if s.listen.address %}
18 |
19 | server {
20 | listen {{ s.listen.address }}{% if s.listen.protocol == "udp" %} {{ s.listen.protocol }}{% endif %};
21 | status_zone {{ s.name | replace(" ", "_") }};
22 | {% endif -%}
23 | {% endif -%}
24 |
25 | {% if s.resolver -%}
26 | include "{{ ncgconfig.nms.resolver_dir }}/{{ s.resolver | replace(" ", "_") }}.conf";
27 | {% endif -%}
28 |
29 | {# --- TLS section --- #}
30 | {%- if s.listen.tls -%}
31 | {%- if s.listen.tls.certificate -%}
32 | ssl_certificate {{ ncgconfig.nms.certs_dir }}/{{ s.listen.tls.certificate }}.crt;
33 | {% endif -%}
34 | {%- if s.listen.tls.key -%}
35 | ssl_certificate_key {{ ncgconfig.nms.certs_dir }}/{{ s.listen.tls.key }}.key;
36 | {% endif -%}
37 | {% if s.listen.tls.ciphers -%}
38 | ssl_ciphers {{ s.listen.tls.ciphers }};
39 | {% endif -%}
40 | {% if s.listen.tls.protocols -%}
41 | ssl_protocols{% for p in s.listen.tls.protocols %} {{ p }}{% endfor %};
42 | {% endif %}
43 | {% endif %}
44 |
45 | {% if s.upstream -%}
46 | proxy_pass {{ s.upstream }};
47 | {% endif %}
48 |
49 | {% if s.snippet and s.snippet.content %}{{ s.snippet.content | b64decode }}{% endif %}
50 |
51 | {%- if s.listen %}
52 | {%- if s.listen.address %}
53 |
54 | }
55 | {% endif -%}
56 | {% endif -%}
57 |
58 | {%- endfor %}
59 |
--------------------------------------------------------------------------------
/templates/v5.3/visibility/moesif/http.tmpl:
--------------------------------------------------------------------------------
1 | # Moesif integration - https://www.moesif.com/docs/server-integration/nginx-openresty/
2 | # URI: {{ loc.uri }}
3 | # application ID: {{ vis.moesif.application_id }}
4 |
5 | lua_shared_dict moesif_conf 5m;
6 |
7 | init_by_lua_block {
8 | local config = ngx.shared.moesif_conf;
9 | config:set("application_id", "{{ vis.moesif.application_id }}")
10 | }
11 |
12 | lua_package_cpath ";;${prefix}?.so;${prefix}src/?.so;/usr/share/lua/5.1/lua/resty/moesif/?.so;/usr/share/lua/5.1/?.so;/usr/lib64/lua/5.1/?.so;/usr/lib/lua/5.1/?.so;/usr/local/openresty/luajit/share/lua/5.1/lua/resty?.so;/usr/local/share/lua/5.1/resty/moesif/?.so;{{ vis.moesif.plugin_path }}/?.so";
13 | lua_package_path ";;${prefix}?.lua;${prefix}src/?.lua;/usr/share/lua/5.1/lua/resty/moesif/?.lua;/usr/share/lua/5.1/?.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib/lua/5.1/?.lua;/usr/local/openresty/luajit/share/lua/5.1/lua/resty?.lua;/usr/local/share/lua/5.1/resty/moesif/?.lua;{{ vis.moesif.plugin_path }}/?.lua";
14 |
15 |
--------------------------------------------------------------------------------
/templates/v5.3/visibility/moesif/server.tmpl:
--------------------------------------------------------------------------------
1 | # Moesif integration - https://www.moesif.com/docs/server-integration/nginx-openresty/
2 | # URI: {{ loc.uri }}
3 | # application ID: {{ vis.moesif.application_id }}
4 |
5 | # Define the variables Moesif requires
6 | set $moesif_user_id nil;
7 | set $moesif_company_id nil;
8 | set $moesif_req_body nil;
9 | set $moesif_res_body nil;
10 |
11 | # Optionally, set moesif_user_id and moesif_company_id such from a request header or NGINX var to identify customer
12 | header_filter_by_lua_block {
13 | ngx.var.moesif_user_id = ngx.req.get_headers()["X-User-Id"]
14 | ngx.var.moesif_company_id = ngx.req.get_headers()["X-Company-Id"]
15 | }
16 |
17 | # Add Moesif plugin
18 | access_by_lua_file {{ vis.moesif.plugin_path }}/read_req_body.lua;
19 | body_filter_by_lua_file {{ vis.moesif.plugin_path }}/read_res_body.lua;
20 | log_by_lua_file {{ vis.moesif.plugin_path }}/send_event.lua;
21 |
22 |
--------------------------------------------------------------------------------