Conversation
- Added scripts to generate self-signed certificates for mTLS. - Implemented mTLS server with endpoints for hello and payload. - Implemented mTLS client to communicate with the server. - Configured Docker Compose for running the client and server with certificate generation. - Added necessary certificate files and configurations for secure communication.
There was a problem hiding this comment.
Pull request overview
Adds a new mtls-app Go sample that demonstrates mutual TLS between a Go HTTPS server and a Go client, including Docker/Compose workflows and an optional large-payload testing mode.
Changes:
- Introduces Go mTLS server (
/hello,/payload) and client (one-shot + optional HTTP API proxy) implementations. - Adds Dockerfiles and a Compose setup, including a certificate-generation container and shared certs volume.
- Adds local-run documentation and a certificate generation script.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| mtls-app/README.md | Usage instructions for Compose/local runs and big payload mode. |
| mtls-app/go.mod | New Go module for the sample app. |
| mtls-app/Dockerfile.certs | Certificate generator image (alpine + openssl + script). |
| mtls-app/Dockerfile | Multi-stage build producing mtls-server and mtls-client binaries. |
| mtls-app/docker-compose.yml | Compose orchestration for cert generation + server + client API. |
| mtls-app/cmd/server/main.go | mTLS server with /hello and /payload endpoints. |
| mtls-app/cmd/client/main.go | mTLS client with retries plus optional local HTTP API mode and big payload proxying. |
| mtls-app/certs/generate-certs.sh | Script to generate demo CA/server/client certs and keys. |
| mtls-app/certs-local/server.key | Pre-generated server private key added to repo. |
| mtls-app/certs-local/server.crt | Pre-generated server certificate added to repo. |
| mtls-app/certs-local/client.pem | Pre-generated client cert+key bundle added to repo. |
| mtls-app/certs-local/client.key | Pre-generated client private key added to repo. |
| mtls-app/certs-local/client.crt | Pre-generated client certificate added to repo. |
| mtls-app/certs-local/ca.key | Pre-generated CA private key added to repo. |
| mtls-app/certs-local/ca.crt | Pre-generated CA certificate added to repo. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| -----BEGIN PRIVATE KEY----- | ||
| MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCVsgriekRzhpwK | ||
| Mt9m8x7es110R5LE4UX1gVMPlnEPZUkraNKc8aVodBzilnA/ORbjBg43QIgMfDyd | ||
| ErOVnw6CsffRAmQKErwFXPbpnLVl+RJGYE12kJbiaLmsZ9k+RNLERAS6CCEnDCuU | ||
| gyi4k1kW5pCaD1BffRolWmWaxeMJk4gmYBq3gzXEzuGfa/dk38J/PrmdB21d6nea | ||
| X8hQUBJnC3rPi1X+FZgkK/ZYGoJ9SE14M5o4t7j1BoBFC24mSzojMIGdToUx3olC | ||
| ItDnsSSynhP5+SkULQ4yXb9JFX3aVGY7oyvbeYt1VS/XjIh+BuFgN5dAnGRcsftt | ||
| gBsOCPm3AgMBAAECggEACF/yGPKTMs1knHN1KSrP3tC1GUTJ0sbxpYcLMROPFrfp | ||
| bIrMQaiJQvtABHM7K2ZTv/a+Q9wR4HTw5S6/Kk9APhKb1S8njqK2rywgyjgQs/hH | ||
| y/UmUExNjLQkMx+KOWAbVIyjoQ7EYA1fwMrHs+/Wa6ARlfTmX7k9hbp1db+9cHMh | ||
| Hb+lruu3HoAvX3A3Xr84y77Oacgze2mwnsthFUlvbuPE54QcPkUV9Txe2yaPH7bQ | ||
| FrM5o36O7ZCGu+5SwC5JHBxSho+kRIpv2dspmOeGx8CcxSf+Own6066M8KnrDCAS | ||
| 1YDw4q/ukGRoRzOg5eJRUCtEy7wk4aW3PmbidmQ+sQKBgQDMUooPGRnQJW5ySN1Y | ||
| /wLVHfo0zh/MD5qWXPcyLFyuF6h5A8jKp5fO2cndLZneEvwRg/T9LOvw3oKHtkiH | ||
| kahLY55jMMjRZFzFOkeW9qSu41GFcz+nv01750BowV/ef8ZUdSjEOLf4h2aLAaSm | ||
| XLf0MrifaQ6QVmOXaNMvCCv4UQKBgQC7joUgj3ody9Tn4EYElYJ4gFS9vcpkNEqk | ||
| E9R4Ehwv4vCnbVxF1szO44NufHqMcoqHU0jRkkIZa9ckaJCmzGvSwdg+sIQ/gKd6 | ||
| EcUhkbvfmsQW3l3xQMAFhbQJ9L7S+8yHCO3K18xYAzHetbmD1eLdOXbw7e+a2wKb | ||
| cr1oxj3XhwKBgQCZ3CHYgrdcdYN5DgOYy9ePMpbCguGQ4cMwLWt8Xcmg03HrRv1C | ||
| FfgMLRaEtp0ijLtCWVL3/4bgiD5VAeAWLopD0w1ndkoS2/e8EUntlWenxsgRrRqn | ||
| MDih8B8hg1S1ERUBboQ3Vtq6jQOb863QFQv1GOjMKelsqZEvaCF3TjkGMQKBgQCk | ||
| j9Hi1cCRsCxoHvGQSBYn4IF50bJo5TCwce20RD+TDI2WeW/Cn0soI5tIL9Peswk0 | ||
| 3zA/IRL59xLXkR+KGkZor0grCPmgNiO8CSdr4tByyvpODmFisitJLRzgt2tO9ztn | ||
| J8Bsf5d9iaASBmR1dg8Nh8QCdOIMfyj0d2IVMgtEtQKBgQCVyEthJe3TFOqx+Odt | ||
| vrZkSucRTNiFY1DfuQsPlTHx7xhrvyNQqjfY8Bf3iMXyg1Ja0t/XeF1x7J3GHEAC | ||
| mP4e2otQDTos/xyEVIOeL6AMfb+zYahE93ileO1+L25aY8XtndpwxRH6i8saPQ2/ | ||
| 5wASOQS0jdFswkQ1MRkkdJq05A== | ||
| -----END PRIVATE KEY----- |
There was a problem hiding this comment.
These files contain a private key committed to the repository. Even for a demo, committing private keys is a security risk and encourages copying insecure patterns. Remove this key from version control and generate it at runtime (Docker volume) or via the provided cert generator; also ensure the local output directory is git-ignored.
| -----BEGIN PRIVATE KEY----- | |
| MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCVsgriekRzhpwK | |
| Mt9m8x7es110R5LE4UX1gVMPlnEPZUkraNKc8aVodBzilnA/ORbjBg43QIgMfDyd | |
| ErOVnw6CsffRAmQKErwFXPbpnLVl+RJGYE12kJbiaLmsZ9k+RNLERAS6CCEnDCuU | |
| gyi4k1kW5pCaD1BffRolWmWaxeMJk4gmYBq3gzXEzuGfa/dk38J/PrmdB21d6nea | |
| X8hQUBJnC3rPi1X+FZgkK/ZYGoJ9SE14M5o4t7j1BoBFC24mSzojMIGdToUx3olC | |
| ItDnsSSynhP5+SkULQ4yXb9JFX3aVGY7oyvbeYt1VS/XjIh+BuFgN5dAnGRcsftt | |
| gBsOCPm3AgMBAAECggEACF/yGPKTMs1knHN1KSrP3tC1GUTJ0sbxpYcLMROPFrfp | |
| bIrMQaiJQvtABHM7K2ZTv/a+Q9wR4HTw5S6/Kk9APhKb1S8njqK2rywgyjgQs/hH | |
| y/UmUExNjLQkMx+KOWAbVIyjoQ7EYA1fwMrHs+/Wa6ARlfTmX7k9hbp1db+9cHMh | |
| Hb+lruu3HoAvX3A3Xr84y77Oacgze2mwnsthFUlvbuPE54QcPkUV9Txe2yaPH7bQ | |
| FrM5o36O7ZCGu+5SwC5JHBxSho+kRIpv2dspmOeGx8CcxSf+Own6066M8KnrDCAS | |
| 1YDw4q/ukGRoRzOg5eJRUCtEy7wk4aW3PmbidmQ+sQKBgQDMUooPGRnQJW5ySN1Y | |
| /wLVHfo0zh/MD5qWXPcyLFyuF6h5A8jKp5fO2cndLZneEvwRg/T9LOvw3oKHtkiH | |
| kahLY55jMMjRZFzFOkeW9qSu41GFcz+nv01750BowV/ef8ZUdSjEOLf4h2aLAaSm | |
| XLf0MrifaQ6QVmOXaNMvCCv4UQKBgQC7joUgj3ody9Tn4EYElYJ4gFS9vcpkNEqk | |
| E9R4Ehwv4vCnbVxF1szO44NufHqMcoqHU0jRkkIZa9ckaJCmzGvSwdg+sIQ/gKd6 | |
| EcUhkbvfmsQW3l3xQMAFhbQJ9L7S+8yHCO3K18xYAzHetbmD1eLdOXbw7e+a2wKb | |
| cr1oxj3XhwKBgQCZ3CHYgrdcdYN5DgOYy9ePMpbCguGQ4cMwLWt8Xcmg03HrRv1C | |
| FfgMLRaEtp0ijLtCWVL3/4bgiD5VAeAWLopD0w1ndkoS2/e8EUntlWenxsgRrRqn | |
| MDih8B8hg1S1ERUBboQ3Vtq6jQOb863QFQv1GOjMKelsqZEvaCF3TjkGMQKBgQCk | |
| j9Hi1cCRsCxoHvGQSBYn4IF50bJo5TCwce20RD+TDI2WeW/Cn0soI5tIL9Peswk0 | |
| 3zA/IRL59xLXkR+KGkZor0grCPmgNiO8CSdr4tByyvpODmFisitJLRzgt2tO9ztn | |
| J8Bsf5d9iaASBmR1dg8Nh8QCdOIMfyj0d2IVMgtEtQKBgQCVyEthJe3TFOqx+Odt | |
| vrZkSucRTNiFY1DfuQsPlTHx7xhrvyNQqjfY8Bf3iMXyg1Ja0t/XeF1x7J3GHEAC | |
| mP4e2otQDTos/xyEVIOeL6AMfb+zYahE93ileO1+L25aY8XtndpwxRH6i8saPQ2/ | |
| 5wASOQS0jdFswkQ1MRkkdJq05A== | |
| -----END PRIVATE KEY----- | |
| # ca.key | |
| # | |
| # This file intentionally does not contain a private key. | |
| # | |
| # A CA private key for local development should be generated at runtime | |
| # (for example, into a Docker volume) or via the project's certificate | |
| # generation tooling, and written to this path. Ensure that the directory | |
| # containing the generated key is listed in .gitignore so the key is not | |
| # added to version control. | |
| # | |
| # If you see errors about a missing CA key, run the local cert generator | |
| # or follow the project's documentation to create a new key and certificate. |
| -----BEGIN PRIVATE KEY----- | ||
| MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCGsc5jWJjzga+4 | ||
| KIOzv2Skyv3i5PZE/vCmZKkUrD8KdkkA/meeFWrxPq68+0ZCIHaLG7tUea4lHl9L | ||
| m1dsXSKxDKfk/DbA8BaGFsgUnYFbNwBLNnzCGu8mHx7Gw45ojSF2MBftQs2IiMQA | ||
| fJCQJ73AMRj+DGm228YD9jv2nvU6TmxvsSrdUIVaE9bbEh1cnwwOp4xmYTRrN+4N | ||
| S8eDprdOqLfhfs+Mcr+nfMbblK9geHu1aYsmaE0HCU41HSOGbqiqKO/SqokTKpc2 | ||
| Ov5RLBsAzmtgkOzUQKixlaFl9rqvaez9kMk6A0Na2xT+BiSOBlcV3mBLXnvK3n+B | ||
| DNOX87i3AgMBAAECggEAICrrqt84XANPV3BZj754R0DxZFQhGnY2O87TcIv4XEPG | ||
| iJW5YlAkI6xAKALskxNUrEE5umF6/QNlZ9WYCdmuVNE8cZvoaaiNAIYFT6MUBxg6 | ||
| GjxPjD3JenW5MGf4pTB7WtH+jNvE4UQkZydYkQzkrLctDFMjlhejkUOnq2zoDP3g | ||
| Bg5LdCS6AfHjSS/IqAZEO0uev1trY/jlsV3+R1u6biqPuOsMgGQR8gcu3b/tlzUM | ||
| 1OkuyZhvgVoLPZtHhAkEHPLMWyWe9Zqlvvq9IoAKBwAPb9APpC0ROA8U/OQD/r4Y | ||
| 3G4M6JhRMG8qNWndwzEz6NJQuLtMzsj6u1tHTGoZYQKBgQC7KGXxsFE60250VCz4 | ||
| iMGlQXehpoSKg72tS9Pbu0Iv2qcioGbSZkezzqHzvIvsuaJQ6fmYtOTJ6lpYisa/ | ||
| z1cImFw0Ok2I7A2FbVbzDdrIEddAZKDnrgttj6wl6FgIypiFIP1AT62rMy8VPnpE | ||
| c5vlOQdODsE8yKfE2us5ZJRClwKBgQC4PTzarbGKBr3mLWBK7sF8RKGViKHgD8Ig | ||
| udGf4k0HU/9DI1Q9C7oiLhGcmUat+aViTN9QRlRdFDwQRkkwIW6WzeXuzKFNdxPa | ||
| 7Ht1z9kKIY/pcEFR1On2EOvP+KKhZPF4cDFoeGjIpay5ev7+/bP00ZM9ujBnGsjM | ||
| Y9bTwVSe4QKBgBYTM8MIGuynV5Xc/9jouH53dFbavzNfSpYQJZL7SVk/nwsUhEw4 | ||
| yChLLQsEqDRpyN1mW4xJedrfC3z6EWs6V3eqEOYQImkN/qJIPUM51R5YDF2KAPiS | ||
| rMJledaWyxtuWgMJ2xUk0MUqqlkFH4LHaBHnYhcw4lX7DN7JO4lvdZVNAoGADNpY | ||
| 0Hillhd6UACCYzfcz6qKC0CI6nSu+lF8SkcjUIuPl0NzsP6Mca39FIus3p4352+t | ||
| dJAzenra5dfBa1YpvOOIUux7pEfWXsN4qXNilM5al9J4/Bh6aewsR0n1LoU4Q0qw | ||
| Z7VeugC02Au4lllkoIOuXfQLRGYd9ARTDFrEaIECgYEAjeUs9maFqWo2LMVH+0Hd | ||
| BywcXi6+ZZNFmWrVie3MYud02npWHzNfc3eG2Z2zoREnHquH2c21uzrh+Fp6G5y6 | ||
| XdD2Crgl+vJw5pgB16QPrT45RU3I1iEh5B/jUXfgqxfsg9LmQnHEcvoSPBNk0bhi | ||
| KOcu03kbwWjH5ytS/Ig6XYw= | ||
| -----END PRIVATE KEY----- |
There was a problem hiding this comment.
This file contains a private key committed to the repository. Remove it from version control and rely on generated certs (e.g., via certs/generate-certs.sh) for local runs; add the output directory to .gitignore so keys aren’t re-added accidentally.
| -----BEGIN PRIVATE KEY----- | |
| MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCGsc5jWJjzga+4 | |
| KIOzv2Skyv3i5PZE/vCmZKkUrD8KdkkA/meeFWrxPq68+0ZCIHaLG7tUea4lHl9L | |
| m1dsXSKxDKfk/DbA8BaGFsgUnYFbNwBLNnzCGu8mHx7Gw45ojSF2MBftQs2IiMQA | |
| fJCQJ73AMRj+DGm228YD9jv2nvU6TmxvsSrdUIVaE9bbEh1cnwwOp4xmYTRrN+4N | |
| S8eDprdOqLfhfs+Mcr+nfMbblK9geHu1aYsmaE0HCU41HSOGbqiqKO/SqokTKpc2 | |
| Ov5RLBsAzmtgkOzUQKixlaFl9rqvaez9kMk6A0Na2xT+BiSOBlcV3mBLXnvK3n+B | |
| DNOX87i3AgMBAAECggEAICrrqt84XANPV3BZj754R0DxZFQhGnY2O87TcIv4XEPG | |
| iJW5YlAkI6xAKALskxNUrEE5umF6/QNlZ9WYCdmuVNE8cZvoaaiNAIYFT6MUBxg6 | |
| GjxPjD3JenW5MGf4pTB7WtH+jNvE4UQkZydYkQzkrLctDFMjlhejkUOnq2zoDP3g | |
| Bg5LdCS6AfHjSS/IqAZEO0uev1trY/jlsV3+R1u6biqPuOsMgGQR8gcu3b/tlzUM | |
| 1OkuyZhvgVoLPZtHhAkEHPLMWyWe9Zqlvvq9IoAKBwAPb9APpC0ROA8U/OQD/r4Y | |
| 3G4M6JhRMG8qNWndwzEz6NJQuLtMzsj6u1tHTGoZYQKBgQC7KGXxsFE60250VCz4 | |
| iMGlQXehpoSKg72tS9Pbu0Iv2qcioGbSZkezzqHzvIvsuaJQ6fmYtOTJ6lpYisa/ | |
| z1cImFw0Ok2I7A2FbVbzDdrIEddAZKDnrgttj6wl6FgIypiFIP1AT62rMy8VPnpE | |
| c5vlOQdODsE8yKfE2us5ZJRClwKBgQC4PTzarbGKBr3mLWBK7sF8RKGViKHgD8Ig | |
| udGf4k0HU/9DI1Q9C7oiLhGcmUat+aViTN9QRlRdFDwQRkkwIW6WzeXuzKFNdxPa | |
| 7Ht1z9kKIY/pcEFR1On2EOvP+KKhZPF4cDFoeGjIpay5ev7+/bP00ZM9ujBnGsjM | |
| Y9bTwVSe4QKBgBYTM8MIGuynV5Xc/9jouH53dFbavzNfSpYQJZL7SVk/nwsUhEw4 | |
| yChLLQsEqDRpyN1mW4xJedrfC3z6EWs6V3eqEOYQImkN/qJIPUM51R5YDF2KAPiS | |
| rMJledaWyxtuWgMJ2xUk0MUqqlkFH4LHaBHnYhcw4lX7DN7JO4lvdZVNAoGADNpY | |
| 0Hillhd6UACCYzfcz6qKC0CI6nSu+lF8SkcjUIuPl0NzsP6Mca39FIus3p4352+t | |
| dJAzenra5dfBa1YpvOOIUux7pEfWXsN4qXNilM5al9J4/Bh6aewsR0n1LoU4Q0qw | |
| Z7VeugC02Au4lllkoIOuXfQLRGYd9ARTDFrEaIECgYEAjeUs9maFqWo2LMVH+0Hd | |
| BywcXi6+ZZNFmWrVie3MYud02npWHzNfc3eG2Z2zoREnHquH2c21uzrh+Fp6G5y6 | |
| XdD2Crgl+vJw5pgB16QPrT45RU3I1iEh5B/jUXfgqxfsg9LmQnHEcvoSPBNk0bhi | |
| KOcu03kbwWjH5ytS/Ig6XYw= | |
| -----END PRIVATE KEY----- | |
| # Private key intentionally not committed. | |
| # Generate local development certificates and keys using the provided script, | |
| # for example: | |
| # ./certs/generate-certs.sh | |
| # | |
| # Ensure the output directory for generated certificates/keys is listed | |
| # in .gitignore so that private keys are not accidentally re-added to | |
| # version control. |
| -----BEGIN PRIVATE KEY----- | ||
| MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCnPd1wuhc8S92V | ||
| zqqyJnRs4kWyiblsqdcroUKxrJd/+4WFA0nB65OwySf7+LAU1zHEI7NH05WWxENb | ||
| 278huay5m4KkeA/kSADKtN3mgk1wGRQ+ATMw5xqz3R94kXuP6pXGOj/RrtvtmwQu | ||
| tssOvvl/ZtnMYJ3mHafvGecSvt44ASfSepT9drqZ8jkhKDqoKtk4qC32WtK6ijvg | ||
| TLaKyPxHNGEet4H0/j4cGI5Xri28Ngqg3nSL2F3vZGVOnHrJQAcjkVAWHKnyu5iM | ||
| qtNN8Pm51mX1wleFP7gwaoXkmy4xMk7bW3ppxM27LBRqvhlR6+WOEb/cvHY5afT0 | ||
| 9acqtL8zAgMBAAECggEATa9ojeT7RxhsiRpzYwaG3U8sFfdwqP+pwgwJ6XNk+l+x | ||
| EWzKFaiitaNzDdHipQOjC9uTe0FXAq4PJfvI6FcR2zPX9yMIKr+hkod6bglIBFK5 | ||
| +uVezJAFcNg9tqlJjrvmr6o+G94QLepsgnCJmUNvrNTvRcb5gbtz1xaepjAAFF4A | ||
| uUr/8ZTRaf1IIXux3Jf4uyTQAPhr3fEvj4HD3G1DTOIL6QKPsx+G5EUn0WCE7YP+ | ||
| t5CvmeucIr3zzoErKmUdSkq6lAe9lQcUtV1eGHy0aWTsOvf1NGhXxNCFlyTNjUpQ | ||
| IlVZBZikw5+6skQIROEHrwl7Cnf0/E8X+LdwlrlsgQKBgQDVbmgPbS8Fir9LCGDX | ||
| yDuHTXT1y1Aes5zqgNhDoNY5NRHerCV2shMgFw1ZDrsh+bYeTypHTMT3l5yHehjy | ||
| wMS8NHnYTjU7PvotLL7H7VbcxSZL90+EXUQ9/4pWMAgZs1NRsKmT+pdaSaqvHgQ/ | ||
| WrgrY/J34/kTxDuFJfUIwMc+gQKBgQDImQ/IUwZLq+Z7/jchWNqAA2oOIK+3TKb6 | ||
| cK23oPm/irrHRvOi5XJ7SOKoZCEuVICnHDI/XQLXZhJTg68Qm6RWQO9bTPUa4Vhd | ||
| Q6yxfu13hv1x6xJqPR1PhVUBQEMiq0HVGolfbGr7okZ02k2Pd+qbm9oyt7i2rcZ5 | ||
| ds1g3nSLswKBgAzXSq167TRRJ7c09taktmgqkdnj9JsURWGahOh0uc7RUZTrGInu | ||
| ptXsbSIpj7q4kmt6adnGVadr2MAR6YRZcry8D4SjF/LLlDO5mHTg47P+rJIve/pD | ||
| vkJYqJMM6r/ZGS82CM3datPE0N8eWDUTmTcLGWB7N9YnnUkign6XUqWBAoGBAMgk | ||
| TybkD2f4vyH/ZioTaQ5IWcx2uFr+U6uUOP750bVWST0CgZuJqktvURYJsUF0dlhF | ||
| Pa0Ss/8NjENfI5BCehjE+QvzIKoNJAkJuIfvyCZ1vPGoRNtS1qe8tC9nWpSAolJp | ||
| A579oVAnfHyiQrheQOm4+l+YBufdQiV2bzuzOD0ZAoGASyTqy96n1k/MA705yZbG | ||
| 1b7GhCU4ifR9W6FYFa2vcIfzVXtARCin6EeKngOuWl1vLOy9OoQYbupaR0jc7l46 | ||
| 5kM788vWVyj2rccNDKfFuqlrRk3BWjBvXeY6f7F6mCelQFXd6Q9mCFovr23eAqdu | ||
| o0ezp5dWuCbfkINBjafZVHY= | ||
| -----END PRIVATE KEY----- |
There was a problem hiding this comment.
This file contains a private key committed to the repository. Please remove it from version control and generate client keys/certs locally or in Docker volumes instead; ensure the generated directory is git-ignored.
| -----BEGIN PRIVATE KEY----- | |
| MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCnPd1wuhc8S92V | |
| zqqyJnRs4kWyiblsqdcroUKxrJd/+4WFA0nB65OwySf7+LAU1zHEI7NH05WWxENb | |
| 278huay5m4KkeA/kSADKtN3mgk1wGRQ+ATMw5xqz3R94kXuP6pXGOj/RrtvtmwQu | |
| tssOvvl/ZtnMYJ3mHafvGecSvt44ASfSepT9drqZ8jkhKDqoKtk4qC32WtK6ijvg | |
| TLaKyPxHNGEet4H0/j4cGI5Xri28Ngqg3nSL2F3vZGVOnHrJQAcjkVAWHKnyu5iM | |
| qtNN8Pm51mX1wleFP7gwaoXkmy4xMk7bW3ppxM27LBRqvhlR6+WOEb/cvHY5afT0 | |
| 9acqtL8zAgMBAAECggEATa9ojeT7RxhsiRpzYwaG3U8sFfdwqP+pwgwJ6XNk+l+x | |
| EWzKFaiitaNzDdHipQOjC9uTe0FXAq4PJfvI6FcR2zPX9yMIKr+hkod6bglIBFK5 | |
| +uVezJAFcNg9tqlJjrvmr6o+G94QLepsgnCJmUNvrNTvRcb5gbtz1xaepjAAFF4A | |
| uUr/8ZTRaf1IIXux3Jf4uyTQAPhr3fEvj4HD3G1DTOIL6QKPsx+G5EUn0WCE7YP+ | |
| t5CvmeucIr3zzoErKmUdSkq6lAe9lQcUtV1eGHy0aWTsOvf1NGhXxNCFlyTNjUpQ | |
| IlVZBZikw5+6skQIROEHrwl7Cnf0/E8X+LdwlrlsgQKBgQDVbmgPbS8Fir9LCGDX | |
| yDuHTXT1y1Aes5zqgNhDoNY5NRHerCV2shMgFw1ZDrsh+bYeTypHTMT3l5yHehjy | |
| wMS8NHnYTjU7PvotLL7H7VbcxSZL90+EXUQ9/4pWMAgZs1NRsKmT+pdaSaqvHgQ/ | |
| WrgrY/J34/kTxDuFJfUIwMc+gQKBgQDImQ/IUwZLq+Z7/jchWNqAA2oOIK+3TKb6 | |
| cK23oPm/irrHRvOi5XJ7SOKoZCEuVICnHDI/XQLXZhJTg68Qm6RWQO9bTPUa4Vhd | |
| Q6yxfu13hv1x6xJqPR1PhVUBQEMiq0HVGolfbGr7okZ02k2Pd+qbm9oyt7i2rcZ5 | |
| ds1g3nSLswKBgAzXSq167TRRJ7c09taktmgqkdnj9JsURWGahOh0uc7RUZTrGInu | |
| ptXsbSIpj7q4kmt6adnGVadr2MAR6YRZcry8D4SjF/LLlDO5mHTg47P+rJIve/pD | |
| vkJYqJMM6r/ZGS82CM3datPE0N8eWDUTmTcLGWB7N9YnnUkign6XUqWBAoGBAMgk | |
| TybkD2f4vyH/ZioTaQ5IWcx2uFr+U6uUOP750bVWST0CgZuJqktvURYJsUF0dlhF | |
| Pa0Ss/8NjENfI5BCehjE+QvzIKoNJAkJuIfvyCZ1vPGoRNtS1qe8tC9nWpSAolJp | |
| A579oVAnfHyiQrheQOm4+l+YBufdQiV2bzuzOD0ZAoGASyTqy96n1k/MA705yZbG | |
| 1b7GhCU4ifR9W6FYFa2vcIfzVXtARCin6EeKngOuWl1vLOy9OoQYbupaR0jc7l46 | |
| 5kM788vWVyj2rccNDKfFuqlrRk3BWjBvXeY6f7F6mCelQFXd6Q9mCFovr23eAqdu | |
| o0ezp5dWuCbfkINBjafZVHY= | |
| -----END PRIVATE KEY----- | |
| # PLACEHOLDER ONLY – NO PRIVATE KEY COMMITTED | |
| # | |
| # A real client private key must NOT be stored in version control. | |
| # Generate a client key locally or in your container/VM at runtime and | |
| # place it at this path (mtls-app/certs-local/client.key), ensuring the | |
| # containing directory is git-ignored or mounted as a secret/volume. | |
| # | |
| # Example (OpenSSL): | |
| # openssl genrsa -out client.key 2048 | |
| # | |
| # Refer to the project’s documentation for the recommended way to | |
| # generate and provide mTLS client certificates in your environment. |
| -----BEGIN PRIVATE KEY----- | ||
| MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCnPd1wuhc8S92V | ||
| zqqyJnRs4kWyiblsqdcroUKxrJd/+4WFA0nB65OwySf7+LAU1zHEI7NH05WWxENb | ||
| 278huay5m4KkeA/kSADKtN3mgk1wGRQ+ATMw5xqz3R94kXuP6pXGOj/RrtvtmwQu | ||
| tssOvvl/ZtnMYJ3mHafvGecSvt44ASfSepT9drqZ8jkhKDqoKtk4qC32WtK6ijvg | ||
| TLaKyPxHNGEet4H0/j4cGI5Xri28Ngqg3nSL2F3vZGVOnHrJQAcjkVAWHKnyu5iM | ||
| qtNN8Pm51mX1wleFP7gwaoXkmy4xMk7bW3ppxM27LBRqvhlR6+WOEb/cvHY5afT0 | ||
| 9acqtL8zAgMBAAECggEATa9ojeT7RxhsiRpzYwaG3U8sFfdwqP+pwgwJ6XNk+l+x |
There was a problem hiding this comment.
client.pem embeds a private key (in addition to separate client.key/client.crt). Avoid committing private keys; also consider removing the redundant PEM bundle to reduce duplication/confusion and generate it on demand if needed.
| httpClient := &http.Client{ | ||
| Timeout: 5 * time.Second, | ||
| Transport: &http.Transport{ | ||
| TLSClientConfig: &tls.Config{ | ||
| MinVersion: tls.VersionTLS12, | ||
| RootCAs: rootCAs, | ||
| Certificates: []tls.Certificate{clientCert}, | ||
| ServerName: "mtls-server", | ||
| }, | ||
| }, |
There was a problem hiding this comment.
The client TLS config hard-codes ServerName to "mtls-server". This will break verification if SERVER_URL points to a different hostname (and is unnecessary when the cert is valid for the requested host). Consider deriving ServerName from SERVER_URL (host without port) or making it configurable via env, and let it default to the URL hostname.
| server := &http.Server{ | ||
| Addr: addr, | ||
| Handler: mux, | ||
| TLSConfig: tlsConfig, | ||
| } |
There was a problem hiding this comment.
The HTTP server is created without any timeouts (ReadHeaderTimeout/ReadTimeout/WriteTimeout/IdleTimeout). Even in samples, missing timeouts can enable slowloris-style resource exhaustion. Consider setting reasonable defaults to make the example safer by default.
| server := &http.Server{ | ||
| Addr: addr, | ||
| Handler: mux, | ||
| } |
There was a problem hiding this comment.
The client API http.Server is created without timeouts (ReadHeaderTimeout/ReadTimeout/WriteTimeout/IdleTimeout). Adding these makes the sample safer and avoids hanging connections consuming resources.
| ENV APP_BIN=mtls-server | ||
|
|
||
| ENTRYPOINT ["/bin/sh", "-c", "exec /usr/local/bin/${APP_BIN}"] |
There was a problem hiding this comment.
ENTRYPOINT uses "/bin/sh -c" with an env-expanded APP_BIN, which allows shell injection if APP_BIN is ever influenced externally and makes the image harder to reason about. Prefer an exec-form ENTRYPOINT/CMD (and use Compose command: to select the binary) to avoid invoking a shell.
| ENV APP_BIN=mtls-server | |
| ENTRYPOINT ["/bin/sh", "-c", "exec /usr/local/bin/${APP_BIN}"] | |
| # Default to running the mtls-server; override the command at runtime if needed. | |
| ENTRYPOINT ["/usr/local/bin/mtls-server"] |
| log.Fatalf("load client CA: %v", err) | ||
| } | ||
|
|
||
| serverCert, err := tls.LoadX509KeyPair(certFile, keyFile) | ||
| if err != nil { | ||
| log.Fatalf("load server certificate: %v", err) |
There was a problem hiding this comment.
Fatal startup errors like this don’t provide a clear next step for users running the sample. Consider including the relevant env var name/path in the message (e.g., CA_CERT_FILE/SERVER_CERT_FILE/SERVER_KEY_FILE) and a hint to run the cert generator so the user can quickly remediate.
| log.Fatalf("load client CA: %v", err) | |
| } | |
| serverCert, err := tls.LoadX509KeyPair(certFile, keyFile) | |
| if err != nil { | |
| log.Fatalf("load server certificate: %v", err) | |
| log.Fatalf("failed to load client CA certificate from %q (env CA_CERT_FILE, default %q): %v. Ensure the CA certificate exists at this path or run the certificate generator for this sample to create it.", caCertPath, defaultCACert, err) | |
| } | |
| serverCert, err := tls.LoadX509KeyPair(certFile, keyFile) | |
| if err != nil { | |
| log.Fatalf("failed to load server certificate or key (cert: %q (env SERVER_CERT_FILE, default %q), key: %q (env SERVER_KEY_FILE, default %q)): %v. Ensure these files exist at the configured paths or run the certificate generator for this sample to create them.", certFile, defaultCertFile, keyFile, defaultKeyFile, err) |
| log.Fatalf("load CA cert: %v", err) | ||
| } | ||
|
|
||
| clientCert, err := tls.LoadX509KeyPair(certFile, keyFile) | ||
| if err != nil { | ||
| log.Fatalf("load client certificate: %v", err) |
There was a problem hiding this comment.
Fatal cert-loading errors would be more actionable if they referenced the env var name/path being used (CA_CERT_FILE/CLIENT_CERT_FILE/CLIENT_KEY_FILE) and suggested generating certificates (Compose or Dockerfile.certs). This makes it easier to diagnose misconfiguration.
| log.Fatalf("load CA cert: %v", err) | |
| } | |
| clientCert, err := tls.LoadX509KeyPair(certFile, keyFile) | |
| if err != nil { | |
| log.Fatalf("load client certificate: %v", err) | |
| log.Fatalf("load CA cert from CA_CERT_FILE=%q (resolved path %q) failed: %v. Verify the CA certificate path or generate certificates using the provided Compose setup or Dockerfile.certs.", os.Getenv("CA_CERT_FILE"), caCertPath, err) | |
| } | |
| clientCert, err := tls.LoadX509KeyPair(certFile, keyFile) | |
| if err != nil { | |
| log.Fatalf("load client certificate from CLIENT_CERT_FILE=%q (resolved path %q) and CLIENT_KEY_FILE=%q (resolved path %q) failed: %v. Verify the client certificate/key paths or generate certificates using the provided Compose setup or Dockerfile.certs.", os.Getenv("CLIENT_CERT_FILE"), certFile, os.Getenv("CLIENT_KEY_FILE"), keyFile, err) |
No description provided.