Skip to content
Snippets Groups Projects
Commit e53b7579 authored by tom.ryser's avatar tom.ryser :carousel_horse:
Browse files

End of project

parents
Branches
No related tags found
No related merge requests found
20230126115153.png

43 KiB

20230126115257.png

34.1 KiB

20230126115500.png

63.5 KiB

20230126115520.png

50.9 KiB

20230126115603.png

50.1 KiB

20230130041332.png

47.1 KiB

20230130042045.png

14.3 KiB

20230130043622.png

41.3 KiB

20230130045344.png

28.1 KiB

20230130054711.png

72.6 KiB

20230130060201.png

90.3 KiB

20230130060242.png

82.6 KiB

20230130062212.png

83.6 KiB

20230130071204.png

68.6 KiB

# syntax=docker/dockerfile:1
FROM golang:1.18-alpine
WORKDIR /app
COPY go.mod .
COPY go.sum .
RUN go mod download
COPY *.go ./
RUN go get .
RUN go build -o /appsec
EXPOSE 8080
CMD [ "/appsec" ]
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>Raport.md</title>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<style>
/* https://github.com/microsoft/vscode/blob/master/extensions/markdown-language-features/media/markdown.css */
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
body {
font-family: var(--vscode-markdown-font-family, -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif);
font-size: var(--vscode-markdown-font-size, 14px);
padding: 0 26px;
line-height: var(--vscode-markdown-line-height, 22px);
word-wrap: break-word;
}
#code-csp-warning {
position: fixed;
top: 0;
right: 0;
color: white;
margin: 16px;
text-align: center;
font-size: 12px;
font-family: sans-serif;
background-color:#444444;
cursor: pointer;
padding: 6px;
box-shadow: 1px 1px 1px rgba(0,0,0,.25);
}
#code-csp-warning:hover {
text-decoration: none;
background-color:#007acc;
box-shadow: 2px 2px 2px rgba(0,0,0,.25);
}
body.scrollBeyondLastLine {
margin-bottom: calc(100vh - 22px);
}
body.showEditorSelection .code-line {
position: relative;
}
body.showEditorSelection .code-active-line:before,
body.showEditorSelection .code-line:hover:before {
content: "";
display: block;
position: absolute;
top: 0;
left: -12px;
height: 100%;
}
body.showEditorSelection li.code-active-line:before,
body.showEditorSelection li.code-line:hover:before {
left: -30px;
}
.vscode-light.showEditorSelection .code-active-line:before {
border-left: 3px solid rgba(0, 0, 0, 0.15);
}
.vscode-light.showEditorSelection .code-line:hover:before {
border-left: 3px solid rgba(0, 0, 0, 0.40);
}
.vscode-light.showEditorSelection .code-line .code-line:hover:before {
border-left: none;
}
.vscode-dark.showEditorSelection .code-active-line:before {
border-left: 3px solid rgba(255, 255, 255, 0.4);
}
.vscode-dark.showEditorSelection .code-line:hover:before {
border-left: 3px solid rgba(255, 255, 255, 0.60);
}
.vscode-dark.showEditorSelection .code-line .code-line:hover:before {
border-left: none;
}
.vscode-high-contrast.showEditorSelection .code-active-line:before {
border-left: 3px solid rgba(255, 160, 0, 0.7);
}
.vscode-high-contrast.showEditorSelection .code-line:hover:before {
border-left: 3px solid rgba(255, 160, 0, 1);
}
.vscode-high-contrast.showEditorSelection .code-line .code-line:hover:before {
border-left: none;
}
img {
max-width: 100%;
max-height: 100%;
}
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
a:focus,
input:focus,
select:focus,
textarea:focus {
outline: 1px solid -webkit-focus-ring-color;
outline-offset: -1px;
}
hr {
border: 0;
height: 2px;
border-bottom: 2px solid;
}
h1 {
padding-bottom: 0.3em;
line-height: 1.2;
border-bottom-width: 1px;
border-bottom-style: solid;
}
h1, h2, h3 {
font-weight: normal;
}
table {
border-collapse: collapse;
}
table > thead > tr > th {
text-align: left;
border-bottom: 1px solid;
}
table > thead > tr > th,
table > thead > tr > td,
table > tbody > tr > th,
table > tbody > tr > td {
padding: 5px 10px;
}
table > tbody > tr + tr > td {
border-top: 1px solid;
}
blockquote {
margin: 0 7px 0 5px;
padding: 0 16px 0 10px;
border-left-width: 5px;
border-left-style: solid;
}
code {
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
font-size: 1em;
line-height: 1.357em;
}
body.wordWrap pre {
white-space: pre-wrap;
}
pre:not(.hljs),
pre.hljs code > div {
padding: 16px;
border-radius: 3px;
overflow: auto;
}
pre code {
color: var(--vscode-editor-foreground);
tab-size: 4;
}
/** Theming */
.vscode-light pre {
background-color: rgba(220, 220, 220, 0.4);
}
.vscode-dark pre {
background-color: rgba(10, 10, 10, 0.4);
}
.vscode-high-contrast pre {
background-color: rgb(0, 0, 0);
}
.vscode-high-contrast h1 {
border-color: rgb(0, 0, 0);
}
.vscode-light table > thead > tr > th {
border-color: rgba(0, 0, 0, 0.69);
}
.vscode-dark table > thead > tr > th {
border-color: rgba(255, 255, 255, 0.69);
}
.vscode-light h1,
.vscode-light hr,
.vscode-light table > tbody > tr + tr > td {
border-color: rgba(0, 0, 0, 0.18);
}
.vscode-dark h1,
.vscode-dark hr,
.vscode-dark table > tbody > tr + tr > td {
border-color: rgba(255, 255, 255, 0.18);
}
</style>
<style>
/* Tomorrow Theme */
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
/* Original theme - https://github.com/chriskempson/tomorrow-theme */
/* Tomorrow Comment */
.hljs-comment,
.hljs-quote {
color: #8e908c;
}
/* Tomorrow Red */
.hljs-variable,
.hljs-template-variable,
.hljs-tag,
.hljs-name,
.hljs-selector-id,
.hljs-selector-class,
.hljs-regexp,
.hljs-deletion {
color: #c82829;
}
/* Tomorrow Orange */
.hljs-number,
.hljs-built_in,
.hljs-builtin-name,
.hljs-literal,
.hljs-type,
.hljs-params,
.hljs-meta,
.hljs-link {
color: #f5871f;
}
/* Tomorrow Yellow */
.hljs-attribute {
color: #eab700;
}
/* Tomorrow Green */
.hljs-string,
.hljs-symbol,
.hljs-bullet,
.hljs-addition {
color: #718c00;
}
/* Tomorrow Blue */
.hljs-title,
.hljs-section {
color: #4271ae;
}
/* Tomorrow Purple */
.hljs-keyword,
.hljs-selector-tag {
color: #8959a8;
}
.hljs {
display: block;
overflow-x: auto;
color: #4d4d4c;
padding: 0.5em;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}
</style>
<style>
/*
* Markdown PDF CSS
*/
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "Meiryo";
padding: 0 12px;
}
pre {
background-color: #f8f8f8;
border: 1px solid #cccccc;
border-radius: 3px;
overflow-x: auto;
white-space: pre-wrap;
overflow-wrap: break-word;
}
pre:not(.hljs) {
padding: 23px;
line-height: 19px;
}
blockquote {
background: rgba(127, 127, 127, 0.1);
border-color: rgba(0, 122, 204, 0.5);
}
.emoji {
height: 1.4em;
}
code {
font-size: 14px;
line-height: 19px;
}
/* for inline code */
:not(pre):not(.hljs) > code {
color: #C9AE75; /* Change the old color so it seems less like an error */
font-size: inherit;
}
/* Page Break : use <div class="page"/> to insert page break
-------------------------------------------------------- */
.page {
page-break-after: always;
}
</style>
<script src="https://unpkg.com/mermaid/dist/mermaid.min.js"></script>
</head>
<body>
<script>
mermaid.initialize({
startOnLoad: true,
theme: document.body.classList.contains('vscode-dark') || document.body.classList.contains('vscode-high-contrast')
? 'dark'
: 'default'
});
</script>
<h1 id="appsec-rapport---tom-ryser">AppSec Rapport - Tom Ryser</h1>
<ul>
<li><a href="#appsec-rapport---tom-ryser">AppSec Rapport - Tom Ryser</a>
<ul>
<li><a href="#api-restful-en-golang">API Restful en Golang</a>
<ul>
<li><a href="#installation">Installation</a></li>
<li><a href="#cr%C3%A9ation-de-lapp-go">Création de l'app Go</a></li>
<li><a href="#containerize-le-code-go-dans-docker">&quot;Containerize&quot; le code go dans Docker</a></li>
</ul>
</li>
<li><a href="#s%C3%A9curisation-avec-tls">Sécurisation avec TLS</a>
<ul>
<li><a href="#pr%C3%A9requis">Prérequis</a></li>
<li><a href="#g%C3%A9n%C3%A9ration-des-cl%C3%A9s-tls">Génération des clés TLS</a></li>
<li><a href="#configuration-nginx">Configuration Nginx</a></li>
<li><a href="#docker-compose">Docker-compose</a></li>
</ul>
</li>
<li><a href="#athentification-et-authorisation">Athentification et Authorisation</a>
<ul>
<li><a href="#impl%C3%A9mentez-les-athentifications">Implémentez les Athentifications</a>
<ul>
<li><a href="#authentification-simple">Authentification simple</a>
<ul>
<li><a href="#resultat">Resultat</a></li>
</ul>
</li>
<li><a href="#authentification-oidc">Authentification OIDC</a></li>
<li><a href="#validation-de-token">Validation de token</a></li>
<li><a href="#test-avec-postman">Test avec Postman</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#gestion-des-donn%C3%A9es-sensibles">Gestion des données sensibles</a></li>
<li><a href="#probl%C3%A8mes-encontr%C3%A9">Problèmes encontré</a></li>
</ul>
</li>
</ul>
<h2 id="api-restful-en-golang">API Restful en Golang</h2>
<h3 id="installation">Installation</h3>
<ul>
<li>Installer Go
<code>$ sudo snap go</code></li>
<li>Installer Docker
<code>$ sudo apt install docker</code></li>
</ul>
<h3 id="cr%C3%A9ation-de-lapp-go">Création de l'app Go</h3>
<p>Dans le dossier appSec j'ai créé un le fichier main.go avec les commandes suivantes.</p>
<pre class="hljs"><code><div>$ go mod init appSec/myApp
$ touch main.go
</div></code></pre>
<p>Le fichier <code>main.go</code> contient les imports du projet, les structures (student &amp; teacher) et leurs déclarations, ainsi que les routes HTTP.</p>
<pre class="hljs"><code><div><span class="hljs-keyword">package</span> main
<span class="hljs-keyword">import</span> (
<span class="hljs-string">"net/http"</span>
<span class="hljs-string">"strings"</span>
<span class="hljs-string">"github.com/gin-gonic/gin"</span>
jwtverifier <span class="hljs-string">"github.com/okta/okta-jwt-verifier-golang"</span>
)
<span class="hljs-comment">// Start of struct</span>
<span class="hljs-keyword">type</span> student <span class="hljs-keyword">struct</span> {
ID <span class="hljs-keyword">string</span> <span class="hljs-string">`json:"id"`</span>
Lastname <span class="hljs-keyword">string</span> <span class="hljs-string">`json:"lastName"`</span>
Name <span class="hljs-keyword">string</span> <span class="hljs-string">`json:"name"`</span>
Filiere <span class="hljs-keyword">string</span> <span class="hljs-string">`json:"filiere"`</span>
}
<span class="hljs-keyword">type</span> teacher <span class="hljs-keyword">struct</span> {
ID <span class="hljs-keyword">string</span> <span class="hljs-string">`json:"UUID"`</span>
Name <span class="hljs-keyword">string</span> <span class="hljs-string">`json:"Name"`</span>
Lastname <span class="hljs-keyword">string</span> <span class="hljs-string">`json:"Last name"`</span>
Class <span class="hljs-keyword">string</span> <span class="hljs-string">`json:"ClassName"`</span>
}
<span class="hljs-comment">// End of struct</span>
<span class="hljs-comment">// Start of data</span>
<span class="hljs-keyword">var</span> students = []student{
{ID: <span class="hljs-string">"1"</span>, Lastname: <span class="hljs-string">"Toto"</span>, Name: <span class="hljs-string">"Tata"</span>, Filiere: <span class="hljs-string">"Architecture"</span>},
{ID: <span class="hljs-string">"2"</span>, Lastname: <span class="hljs-string">"Tom"</span>, Name: <span class="hljs-string">"Ryser"</span>, Filiere: <span class="hljs-string">"Informatique"</span>},
{ID: <span class="hljs-string">"3"</span>, Lastname: <span class="hljs-string">"Doe"</span>, Name: <span class="hljs-string">"maxim"</span>, Filiere: <span class="hljs-string">"Architecture"</span>},
}
<span class="hljs-keyword">var</span> teachers = []teacher{
{ID: <span class="hljs-string">"1"</span>, Lastname: <span class="hljs-string">"Doe"</span>, Name: <span class="hljs-string">"Joe"</span>, Class: <span class="hljs-string">"A"</span>},
{ID: <span class="hljs-string">"2"</span>, Lastname: <span class="hljs-string">"Bob"</span>, Name: <span class="hljs-string">"Martin"</span>, Class: <span class="hljs-string">"B"</span>},
}
<span class="hljs-comment">// End of data</span>
<span class="hljs-comment">// Start of student route functions</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getStudents</span><span class="hljs-params">(c *gin.Context)</span></span> {
c.IndentedJSON(http.StatusOK, students)
}
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getStudentByID</span><span class="hljs-params">(c *gin.Context)</span></span> {
id := c.Param(<span class="hljs-string">"id"</span>)
<span class="hljs-keyword">for</span> _, a := <span class="hljs-keyword">range</span> students {
<span class="hljs-keyword">if</span> a.ID == id {
c.IndentedJSON(http.StatusOK, a)
<span class="hljs-keyword">return</span>
}
}
c.IndentedJSON(http.StatusNotFound, gin.H{<span class="hljs-string">"message"</span>: <span class="hljs-string">"student not found"</span>})
}
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">postStudent</span><span class="hljs-params">(c *gin.Context)</span></span> {
<span class="hljs-keyword">var</span> newStudent student
<span class="hljs-keyword">if</span> err := c.BindJSON(&amp;newStudent); err != <span class="hljs-literal">nil</span> {
<span class="hljs-keyword">return</span>
}
students = <span class="hljs-built_in">append</span>(students, newStudent)
c.IndentedJSON(http.StatusCreated, newStudent)
}
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">deleteStudentById</span><span class="hljs-params">(c *gin.Context)</span></span> {
id := c.Param(<span class="hljs-string">"id"</span>)
index := <span class="hljs-number">0</span>
<span class="hljs-keyword">for</span> _, student := <span class="hljs-keyword">range</span> students {
<span class="hljs-keyword">if</span> student.ID == id {
students = <span class="hljs-built_in">append</span>(students[:index], students[index+<span class="hljs-number">1</span>:]...)
c.IndentedJSON(http.StatusOK, students)
<span class="hljs-keyword">return</span>
}
index += <span class="hljs-number">1</span>
}
c.IndentedJSON(http.StatusNotFound, gin.H{<span class="hljs-string">"message"</span>: <span class="hljs-string">"student not found"</span>})
}
<span class="hljs-comment">// End of student route functions</span>
<span class="hljs-comment">// Start of teacher route functions</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTeachers</span><span class="hljs-params">(c *gin.Context)</span></span> {
c.IndentedJSON(http.StatusOK, teachers)
}
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTeacherById</span><span class="hljs-params">(c *gin.Context)</span></span> {
id := c.Param(<span class="hljs-string">"id"</span>)
<span class="hljs-keyword">for</span> _, teacher := <span class="hljs-keyword">range</span> teachers {
<span class="hljs-keyword">if</span> teacher.ID == id {
c.IndentedJSON(http.StatusOK, teacher)
<span class="hljs-keyword">return</span>
}
}
c.IndentedJSON(http.StatusNotFound, gin.H{<span class="hljs-string">"message"</span>: <span class="hljs-string">"teacher not found"</span>})
}
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">postTeacher</span><span class="hljs-params">(c *gin.Context)</span></span> {
<span class="hljs-keyword">var</span> newTeacher teacher
<span class="hljs-keyword">if</span> err := c.BindJSON(&amp;newTeacher); err != <span class="hljs-literal">nil</span> {
<span class="hljs-keyword">return</span>
}
teachers = <span class="hljs-built_in">append</span>(teachers, newTeacher)
c.IndentedJSON(http.StatusCreated, newTeacher)
}
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">deleteTeacherById</span><span class="hljs-params">(c *gin.Context)</span></span> {
id := c.Param(<span class="hljs-string">"id"</span>)
index := <span class="hljs-number">0</span>
<span class="hljs-keyword">for</span> _, teacher := <span class="hljs-keyword">range</span> teachers {
<span class="hljs-keyword">if</span> teacher.ID == id {
teachers = <span class="hljs-built_in">append</span>(teachers[:index], teachers[index+<span class="hljs-number">1</span>:]...)
c.IndentedJSON(http.StatusOK, teachers)
<span class="hljs-keyword">return</span>
}
index += <span class="hljs-number">1</span>
}
c.IndentedJSON(http.StatusNotFound, gin.H{<span class="hljs-string">"message"</span>: <span class="hljs-string">"teacher not found"</span>})
}
<span class="hljs-comment">// End of teacher route functions</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
r := gin.Default()
r.GET(<span class="hljs-string">"/students"</span>, getStudents)
r.GET(<span class="hljs-string">"/students/:id"</span>, getStudentByID)
r.GET(<span class="hljs-string">"/teachers"</span>, getTeachers)
r.GET(<span class="hljs-string">"/teachers/:id"</span>, getTeacherById)
r.Run(<span class="hljs-string">"localhost:8080"</span>)
}
</div></code></pre>
<p>Comment exécuter le code go et vérifier le résultat.</p>
<p><code>$ go get .</code></p>
<p><code>$ go run .</code></p>
<p><code>$ curl http://localhost:8080/students</code>
<img src="20230130041332.png" alt=""></p>
<h3 id="%22containerize%22-le-code-go-dans-docker">&quot;Containerize&quot; le code go dans Docker</h3>
<p>J'ai créé un fichier Dockerfile avec les instructions pour construire la nouvelle image.</p>
<pre class="hljs"><code><div><span class="hljs-comment"># syntax=docker/dockerfile:1</span>
<span class="hljs-keyword">FROM</span> golang:<span class="hljs-number">1.18</span>-alpine
<span class="hljs-keyword">WORKDIR</span><span class="bash"> /app</span>
<span class="hljs-keyword">COPY</span><span class="bash"> go.mod .</span>
<span class="hljs-keyword">COPY</span><span class="bash"> go.sum .</span>
<span class="hljs-keyword">RUN</span><span class="bash"> go mod download</span>
<span class="hljs-keyword">COPY</span><span class="bash"> *.go ./</span>
<span class="hljs-keyword">RUN</span><span class="bash"> go build -o /appsec</span>
<span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">8080</span>
<span class="hljs-keyword">CMD</span><span class="bash"> [ <span class="hljs-string">"/appsec"</span> ]</span>
</div></code></pre>
<p>Puis j'ai utilisé la commande suivante pour construire l'image que j'ai configurée préalablement.</p>
<pre class="hljs"><code><div>docker build --tag docker-appsec_go .
</div></code></pre>
<p>Lors du démarrage du container je dois utiliser la commande suivante pour qu'il ait accès au port 8080
<code>$ docker run -p 8080:8080 docker-appsec_go</code></p>
<h2 id="s%C3%A9curisation-avec-tls">Sécurisation avec TLS</h2>
<h3 id="pr%C3%A9requis">Prérequis</h3>
<pre class="hljs"><code><div>nginx, docker-compose
Fichier nginx.conf donné par l'enseignant.
$ docker pull nginx
</div></code></pre>
<h3 id="g%C3%A9n%C3%A9ration-des-cl%C3%A9s-tls">Génération des clés TLS</h3>
<p>J'ai utilisé la commande suivante pour générer les clés TLS, J'ai donné les réponses suivantes même si elles ne sont pas importantes.
<code>$ openssl req -x509 -newkey rsa:4096 -keyout certs/key.pem -out certs/cert.pem -days 365 -nodes</code></p>
<pre class="hljs"><code><div>result:
Country name : CH
State : Geneva
Locality : Lancy
Organization : HEPIA
Organizational unit : IT
Common name : Tom
Email : tom.ryser@etu.hesge.ch
</div></code></pre>
<h3 id="configuration-nginx">Configuration Nginx</h3>
<p>Voici le fichier de configuration de Nginx.</p>
<pre class="hljs"><code><div><span class="hljs-attribute">user</span> www www; <span class="hljs-comment">## Default: nobody</span>
<span class="hljs-attribute">worker_processes</span> <span class="hljs-number">5</span>; <span class="hljs-comment">## Default: 1</span>
<span class="hljs-attribute">error_log</span> logs/error.log;
<span class="hljs-attribute">pid</span> logs/nginx.pid;
<span class="hljs-attribute">worker_rlimit_nofile</span> <span class="hljs-number">8192</span>;
<span class="hljs-section">events</span> { }
<span class="hljs-section">http</span> {
<span class="hljs-attribute">map</span> <span class="hljs-variable">$http_upgrade</span> <span class="hljs-variable">$connection_upgrade</span> {
<span class="hljs-attribute">default</span> upgrade;
'' close;
}
<span class="hljs-section">server</span> {
<span class="hljs-attribute">listen</span> <span class="hljs-number">80</span>;
<span class="hljs-attribute">server_name</span> localhost;
<span class="hljs-attribute">return</span> <span class="hljs-number">301</span> https://localhost<span class="hljs-variable">$request_uri</span>;
}
<span class="hljs-section">server</span> {
<span class="hljs-attribute">listen</span> <span class="hljs-number">443</span> ssl;
<span class="hljs-attribute">server_name</span> localhost;
<span class="hljs-attribute">ssl_certificate</span> /certs/cert.pem;
<span class="hljs-attribute">ssl_certificate_key</span> /certs/key.pem;
<span class="hljs-attribute">access_log</span> /var/log/nginx/data-access.log combined;
<span class="hljs-attribute">location</span> / {
<span class="hljs-attribute">proxy_pass</span> http://appSec:8080/;
<span class="hljs-attribute">proxy_set_header</span> X-Real-IP <span class="hljs-variable">$remote_addr</span>;
<span class="hljs-attribute">proxy_set_header</span> X-Forwarded-For <span class="hljs-variable">$remote_addr</span>;
<span class="hljs-attribute">proxy_set_header</span> Host <span class="hljs-variable">$host</span>;
<span class="hljs-attribute">proxy_set_header</span> X-Forwarded-Proto <span class="hljs-variable">$scheme</span>;
<span class="hljs-comment">#proxy_redirect http://shiny:3838/ $scheme://$http_host/;</span>
<span class="hljs-attribute">proxy_http_version</span> <span class="hljs-number">1</span>.<span class="hljs-number">1</span>;
<span class="hljs-attribute">proxy_set_header</span> Upgrade <span class="hljs-variable">$http_upgrade</span>;
<span class="hljs-attribute">proxy_set_header</span> Connection <span class="hljs-variable">$connection_upgrade</span>;
<span class="hljs-attribute">proxy_read_timeout</span> <span class="hljs-number">20d</span>;
<span class="hljs-attribute">proxy_buffering</span> <span class="hljs-literal">off</span>;
}
}
}
</div></code></pre>
<h3 id="docker-compose">Docker-compose</h3>
<p>J'ai créé le fichier <code>docker-compose.yml</code> avec le contenu suivant.</p>
<pre class="hljs"><code><div><span class="hljs-attr">version:</span> <span class="hljs-string">'3'</span>
<span class="hljs-attr">services:</span>
<span class="hljs-attr">nginx:</span>
<span class="hljs-attr">image:</span> <span class="hljs-string">nginx:latest</span>
<span class="hljs-attr">container_name:</span> <span class="hljs-string">nginx</span>
<span class="hljs-attr">volumes:</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">.:/nginx.conf</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">./certs:/certs</span>
<span class="hljs-attr">ports:</span>
<span class="hljs-bullet">-</span> <span class="hljs-number">80</span><span class="hljs-string">:80</span>
<span class="hljs-bullet">-</span> <span class="hljs-number">443</span><span class="hljs-string">:443</span>
<span class="hljs-attr">appsec:</span>
<span class="hljs-attr">image:</span> <span class="hljs-string">docker-appsec_go:latest</span>
<span class="hljs-attr">container_name:</span> <span class="hljs-string">appsec</span>
<span class="hljs-attr">expose:</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">"8080"</span>
</div></code></pre>
<p>Puis j'ai utilisé la commande <code>$ docker compose up -d</code> pour construire le docker.
Maintenant quand je vais sur &quot;localhost:8080/students&quot; J'ai une erreur &quot;connection refused&quot;. L'erreur semble provenir de docker, mais je ne sais pas pourquoi.
<img src="20230130042045.png" alt=""></p>
<h2 id="athentification-et-authorisation">Athentification et Authorisation</h2>
<h3 id="impl%C3%A9mentez-les-athentifications">Implémentez les Athentifications</h3>
<h4 id="authentification-simple">Authentification simple</h4>
<p>Pour l'authentification simple, j'ai rajouter 2 groupes:</p>
<ul>
<li>AuthorizedGet
<ul>
<li>user1 (admin)</li>
<li>user2 (visiteur)</li>
</ul>
</li>
<li>authorizedAll
<ul>
<li>user1 (admin)</li>
</ul>
</li>
</ul>
<pre class="hljs"><code><div>r := gin.Default()
authorizedGet := r.Group(<span class="hljs-string">"/"</span>, gin.BasicAuth(gin.Accounts{
<span class="hljs-string">"foo"</span>: <span class="hljs-string">"bar"</span>,
<span class="hljs-string">"aristote"</span>: <span class="hljs-string">"Eucl1de"</span>,
}))
authorizedAll := r.Group(<span class="hljs-string">"/"</span>, gin.BasicAuth(gin.Accounts{
<span class="hljs-string">"aristote"</span>: <span class="hljs-string">"Eucl1de"</span>,
}))
</div></code></pre>
<h5 id="resultat">Resultat</h5>
<p><img src="20230130043622.png" alt=""></p>
<h4 id="authentification-oidc">Authentification OIDC</h4>
<p>J'ai commencé par créer 3 utilisateurs dans okta.
<img src="20230126115257.png" alt=""></p>
<p>Puis j'ai créer une intégration d'application.</p>
<p><img src="20230126115500.png" alt=""><br>
<img src="20230126115520.png" alt=""><br>
<img src="20230126115603.png" alt=""></p>
<h4 id="validation-de-token">Validation de token</h4>
<p>Après avoir configuré Okta j'ai dû installer le paquet Okta pour l'application go, et l'ajouter dans les imports.</p>
<pre class="hljs"><code><div>$ go get -u github.com/okta/okta-jwt-verifier-golang
</div></code></pre>
<pre class="hljs"><code><div><span class="hljs-keyword">import</span> (
<span class="hljs-string">"net/http"</span>
<span class="hljs-string">"github.com/gin-gonic/gin"</span>
<span class="hljs-string">"github.com/okta/okta-jwt-verifier-golang"</span>
<span class="hljs-string">"strings"</span>
)
</div></code></pre>
<p>Ajout de la fonction pour valider le token</p>
<pre class="hljs"><code><div><span class="hljs-keyword">var</span> toValidate = <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>{
<span class="hljs-string">"aud"</span>: <span class="hljs-string">"api://default"</span>,
<span class="hljs-string">"cid"</span>: <span class="hljs-string">"&lt;client-id&gt;"</span>,
}
</div></code></pre>
<p>Il faut remplacer <code>&lt;client-id&gt;</code> par la valeur correspondant à l'audience.
<img src="20230130045344.png" alt=""></p>
<p>Pour finir il faut valider le token, et pour ce faire J'ai modifié mon import.</p>
<pre class="hljs"><code><div><span class="hljs-keyword">import</span> (
<span class="hljs-string">"net/http"</span>
<span class="hljs-string">"os"</span>
<span class="hljs-string">"strings"</span>
<span class="hljs-string">"github.com/gin-gonic/gin"</span>
jwtverifier <span class="hljs-string">"github.com/okta/okta-jwt-verifier-golang"</span>
)
</div></code></pre>
<p>Puis j'ai rajouter une fonction <code>verify()</code>.</p>
<pre class="hljs"><code><div><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">verify</span><span class="hljs-params">(c *gin.Context)</span> <span class="hljs-title">bool</span></span> {
status := <span class="hljs-literal">true</span>
token := c.Request.Header.Get(<span class="hljs-string">"Authorization"</span>)
<span class="hljs-keyword">if</span> strings.HasPrefix(token, <span class="hljs-string">"Bearer "</span>) {
token = strings.TrimPrefix(token, <span class="hljs-string">"Bearer "</span>)
verifierSetup := jwtverifier.JwtVerifier{
Issuer: <span class="hljs-string">"https://"</span> + os.Getenv(<span class="hljs-string">"OKTA_DOMAIN"</span>) + <span class="hljs-string">"/oauth2/default"</span>,
ClaimsToValidate: toValidate,
}
verifier := verifierSetup.New()
_, err := verifier.VerifyAccessToken(token)
<span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
c.String(http.StatusForbidden, err.Error())
<span class="hljs-built_in">print</span>(err.Error())
status = <span class="hljs-literal">false</span>
}
} <span class="hljs-keyword">else</span> {
c.String(http.StatusUnauthorized, <span class="hljs-string">"Unauthorized"</span>)
status = <span class="hljs-literal">false</span>
}
<span class="hljs-keyword">return</span> status
}
</div></code></pre>
<p>source: https://developer.okta.com/blog/2021/02/17/building-and-securing-a-go-and-gin-web-application#how-to-validate-an-access-token-in-go</p>
<h4 id="test-avec-postman">Test avec Postman</h4>
<ul>
<li>Installation
<ul>
<li>Pour installer postman j'ai utilisé la commande<pre class="hljs"><code><div>$ sudo snap install postman
</div></code></pre>
</li>
</ul>
</li>
<li>Configuration
<ul>
<li><img src="20230130060242.png" alt=""></li>
<li></li>
</ul>
</li>
<li>Obtention du token
<ul>
<li>Au bas de la page se trouve un bouton &quot;Get new access token&quot; qui ouvre un navigateur, après avoir entré les informations de login d'un utilisateur, l'on obtient un token d'accès.</li>
<li><img src="20230130060201.png" alt=""></li>
</ul>
</li>
<li>Ajout des droits dans le <code>main.go</code></li>
</ul>
<pre class="hljs"><code><div> <span class="hljs-comment">//OKTA auth</span>
authorization[<span class="hljs-string">"bob.idiot@gmail.com"</span>] = <span class="hljs-built_in">append</span>(authorization[<span class="hljs-string">"bob.idiot@gmail.com"</span>], <span class="hljs-string">"GET"</span>)
authorization[<span class="hljs-string">"jean.intellignet@gmail.com"</span>] = <span class="hljs-built_in">append</span>(authorization[<span class="hljs-string">"jean.intellignet@gmail.com"</span>], <span class="hljs-string">"GET"</span>, <span class="hljs-string">"POST"</span>, <span class="hljs-string">"DELETE"</span>, <span class="hljs-string">"DELETE"</span>)
authorizedOkta := r.Group(<span class="hljs-string">"/"</span>)
authorizedOkta.GET(<span class="hljs-string">"/students"</span>, getStudents)
authorizedOkta.GET(<span class="hljs-string">"/student/:id"</span>, getStudentByID)
authorizedOkta.POST(<span class="hljs-string">"/students"</span>, postStudent)
authorizedOkta.DELETE(<span class="hljs-string">"/student/:id"</span>, deleteStudentById)
authorizedOkta.GET(<span class="hljs-string">"/teachers"</span>, getTeachers)
authorizedOkta.GET(<span class="hljs-string">"/teacher/:id"</span>, getTeacherById)
authorizedOkta.POST(<span class="hljs-string">"/teachers"</span>, postTeacher)
authorizedOkta.DELETE(<span class="hljs-string">"/teacher/:id"</span>, deleteTeacherById)
</div></code></pre>
<p><img src="20230130071204.png" alt=""></p>
<h2 id="gestion-des-donn%C3%A9es-sensibles">Gestion des données sensibles</h2>
<p>Pour cette partie j'ai modifier mon code pour cacher les identifiants écrit en claire.
Pour ce faire j'ai créer un fichier <code>.env</code> dont on appel la correspondence comme ceci <code>os.Getenv(&quot;FOO)</code></p>
<pre class="hljs"><code><div>FOO=&quot;foo:bar&quot;
ARI=&quot;aristote:Euclide&quot;
</div></code></pre>
<p>Je n'ai pas eu le temps d'aller plus loin.</p>
<h2 id="probl%C3%A8mes-encontr%C3%A9">Problèmes encontré</h2>
<p>Lors de ce projet j'ai été confronté à plusieurs problèmes.</p>
<ul>
<li>Docker
<ul>
<li>Lorsque je voulais arrêter un docker, j'obtenais une erreur qui me disait que je n'avais pas les droits nécessaires.</li>
<li>Après avoir complètement désinstallé docker je l'ai réinstaller en version dektop. Ce qui semble avoir fixé mon problème.</li>
<li>J'ai par la suite eu de nouveaux problèmes avec docker et j'ai donc continué le projet sans.</li>
</ul>
</li>
<li>Postman
<ul>
<li>Après avoir installé l'application, au lancement j'ai obtenu une erreur qui faisait planter l'application.</li>
<li>J'ai dû réinstaller l'application 2 fois et suis suivi des tutos différents pour chaque installation.</li>
</ul>
</li>
</ul>
</body>
</html>
Raport.jpeg

2.31 MiB

Raport.md 0 → 100644
# AppSec Rapport - Tom Ryser
- [AppSec Rapport - Tom Ryser](#appsec-rapport---tom-ryser)
- [API Restful en Golang](#api-restful-en-golang)
- [Installation](#installation)
- [Création de l'app Go](#création-de-lapp-go)
- ["Containerize" le code go dans Docker](#containerize-le-code-go-dans-docker)
- [Sécurisation avec TLS](#sécurisation-avec-tls)
- [Prérequis](#prérequis)
- [Génération des clés TLS](#génération-des-clés-tls)
- [Configuration Nginx](#configuration-nginx)
- [Docker-compose](#docker-compose)
- [Athentification et Authorisation](#athentification-et-authorisation)
- [Implémentez les Athentifications](#implémentez-les-athentifications)
- [Authentification simple](#authentification-simple)
- [Resultat](#resultat)
- [Authentification OIDC](#authentification-oidc)
- [Validation de token](#validation-de-token)
- [Test avec Postman](#test-avec-postman)
- [Gestion des données sensibles](#gestion-des-données-sensibles)
- [Problèmes encontré](#problèmes-encontré)
## API Restful en Golang
### Installation
- Installer Go
`$ sudo snap go`
- Installer Docker
`$ sudo apt install docker`
### Création de l'app Go
Dans le dossier appSec j'ai créé un le fichier main.go avec les commandes suivantes.
```
$ go mod init appSec/myApp
$ touch main.go
```
Le fichier `main.go` contient les imports du projet, les structures (student & teacher) et leurs déclarations, ainsi que les routes HTTP.
```go
package main
import (
"net/http"
"strings"
"github.com/gin-gonic/gin"
jwtverifier "github.com/okta/okta-jwt-verifier-golang"
)
// Start of struct
type student struct {
ID string `json:"id"`
Lastname string `json:"lastName"`
Name string `json:"name"`
Filiere string `json:"filiere"`
}
type teacher struct {
ID string `json:"UUID"`
Name string `json:"Name"`
Lastname string `json:"Last name"`
Class string `json:"ClassName"`
}
// End of struct
// Start of data
var students = []student{
{ID: "1", Lastname: "Toto", Name: "Tata", Filiere: "Architecture"},
{ID: "2", Lastname: "Tom", Name: "Ryser", Filiere: "Informatique"},
{ID: "3", Lastname: "Doe", Name: "maxim", Filiere: "Architecture"},
}
var teachers = []teacher{
{ID: "1", Lastname: "Doe", Name: "Joe", Class: "A"},
{ID: "2", Lastname: "Bob", Name: "Martin", Class: "B"},
}
// End of data
// Start of student route functions
func getStudents(c *gin.Context) {
c.IndentedJSON(http.StatusOK, students)
}
func getStudentByID(c *gin.Context) {
id := c.Param("id")
for _, a := range students {
if a.ID == id {
c.IndentedJSON(http.StatusOK, a)
return
}
}
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "student not found"})
}
func postStudent(c *gin.Context) {
var newStudent student
if err := c.BindJSON(&newStudent); err != nil {
return
}
students = append(students, newStudent)
c.IndentedJSON(http.StatusCreated, newStudent)
}
func deleteStudentById(c *gin.Context) {
id := c.Param("id")
index := 0
for _, student := range students {
if student.ID == id {
students = append(students[:index], students[index+1:]...)
c.IndentedJSON(http.StatusOK, students)
return
}
index += 1
}
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "student not found"})
}
// End of student route functions
// Start of teacher route functions
func getTeachers(c *gin.Context) {
c.IndentedJSON(http.StatusOK, teachers)
}
func getTeacherById(c *gin.Context) {
id := c.Param("id")
for _, teacher := range teachers {
if teacher.ID == id {
c.IndentedJSON(http.StatusOK, teacher)
return
}
}
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "teacher not found"})
}
func postTeacher(c *gin.Context) {
var newTeacher teacher
if err := c.BindJSON(&newTeacher); err != nil {
return
}
teachers = append(teachers, newTeacher)
c.IndentedJSON(http.StatusCreated, newTeacher)
}
func deleteTeacherById(c *gin.Context) {
id := c.Param("id")
index := 0
for _, teacher := range teachers {
if teacher.ID == id {
teachers = append(teachers[:index], teachers[index+1:]...)
c.IndentedJSON(http.StatusOK, teachers)
return
}
index += 1
}
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "teacher not found"})
}
// End of teacher route functions
func main() {
r := gin.Default()
r.GET("/students", getStudents)
r.GET("/students/:id", getStudentByID)
r.GET("/teachers", getTeachers)
r.GET("/teachers/:id", getTeacherById)
r.Run("localhost:8080")
}
```
Comment exécuter le code go et vérifier le résultat.
`$ go get .`
`$ go run .`
`$ curl http://localhost:8080/students`
![](20230130041332.png)
### "Containerize" le code go dans Docker
J'ai créé un fichier Dockerfile avec les instructions pour construire la nouvelle image.
```dockerfile
# syntax=docker/dockerfile:1
FROM golang:1.18-alpine
WORKDIR /app
COPY go.mod .
COPY go.sum .
RUN go mod download
COPY *.go ./
RUN go build -o /appsec
EXPOSE 8080
CMD [ "/appsec" ]
```
Puis j'ai utilisé la commande suivante pour construire l'image que j'ai configurée préalablement.
```
docker build --tag docker-appsec_go .
```
Lors du démarrage du container je dois utiliser la commande suivante pour qu'il ait accès au port 8080
`$ docker run -p 8080:8080 docker-appsec_go`
## Sécurisation avec TLS
### Prérequis
```
nginx, docker-compose
Fichier nginx.conf donné par l'enseignant.
$ docker pull nginx
```
### Génération des clés TLS
J'ai utilisé la commande suivante pour générer les clés TLS, J'ai donné les réponses suivantes même si elles ne sont pas importantes.
`$ openssl req -x509 -newkey rsa:4096 -keyout certs/key.pem -out certs/cert.pem -days 365 -nodes`
```
result:
Country name : CH
State : Geneva
Locality : Lancy
Organization : HEPIA
Organizational unit : IT
Common name : Tom
Email : tom.ryser@etu.hesge.ch
```
### Configuration Nginx
Voici le fichier de configuration de Nginx.
```Nginx
user www www; ## Default: nobody
worker_processes 5; ## Default: 1
error_log logs/error.log;
pid logs/nginx.pid;
worker_rlimit_nofile 8192;
events { }
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name localhost;
return 301 https://localhost$request_uri;
}
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /certs/cert.pem;
ssl_certificate_key /certs/key.pem;
access_log /var/log/nginx/data-access.log combined;
location / {
proxy_pass http://appSec:8080/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
#proxy_redirect http://shiny:3838/ $scheme://$http_host/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 20d;
proxy_buffering off;
}
}
}
```
### Docker-compose
J'ai créé le fichier `docker-compose.yml` avec le contenu suivant.
```yml
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
volumes:
- .:/nginx.conf
- ./certs:/certs
ports:
- 80:80
- 443:443
appsec:
image: docker-appsec_go:latest
container_name: appsec
expose:
- "8080"
```
Puis j'ai utilisé la commande `$ docker compose up -d` pour construire le docker.
Maintenant quand je vais sur "localhost:8080/students" J'ai une erreur "connection refused". L'erreur semble provenir de docker, mais je ne sais pas pourquoi.
![](20230130042045.png)
## Athentification et Authorisation
### Implémentez les Athentifications
#### Authentification simple
Pour l'authentification simple, j'ai rajouter 2 groupes:
- AuthorizedGet
- user1 (admin)
- user2 (visiteur)
- authorizedAll
- user1 (admin)
```go
r := gin.Default()
authorizedGet := r.Group("/", gin.BasicAuth(gin.Accounts{
"foo": "bar",
"aristote": "Eucl1de",
}))
authorizedAll := r.Group("/", gin.BasicAuth(gin.Accounts{
"aristote": "Eucl1de",
}))
```
##### Resultat
![](20230130043622.png)
#### Authentification OIDC
J'ai commencé par créer 3 utilisateurs dans okta.
![](20230126115257.png)
Puis j'ai créer une intégration d'application.
![](20230126115500.png)
![](20230126115520.png)
![](20230126115603.png)
#### Validation de token
Après avoir configuré Okta j'ai dû installer le paquet Okta pour l'application go, et l'ajouter dans les imports.
```
$ go get -u github.com/okta/okta-jwt-verifier-golang
```
```go
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/okta/okta-jwt-verifier-golang"
"strings"
)
```
Ajout de la fonction pour valider le token
```go
var toValidate = map[string]string{
"aud": "api://default",
"cid": "<client-id>",
}
```
Il faut remplacer `<client-id>` par la valeur correspondant à l'audience.
![](20230130045344.png)
Pour finir il faut valider le token, et pour ce faire J'ai modifié mon import.
```go
import (
"net/http"
"os"
"strings"
"github.com/gin-gonic/gin"
jwtverifier "github.com/okta/okta-jwt-verifier-golang"
)
```
Puis j'ai rajouter une fonction `verify()`.
```go
func verify(c *gin.Context) bool {
status := true
token := c.Request.Header.Get("Authorization")
if strings.HasPrefix(token, "Bearer ") {
token = strings.TrimPrefix(token, "Bearer ")
verifierSetup := jwtverifier.JwtVerifier{
Issuer: "https://" + os.Getenv("OKTA_DOMAIN") + "/oauth2/default",
ClaimsToValidate: toValidate,
}
verifier := verifierSetup.New()
_, err := verifier.VerifyAccessToken(token)
if err != nil {
c.String(http.StatusForbidden, err.Error())
print(err.Error())
status = false
}
} else {
c.String(http.StatusUnauthorized, "Unauthorized")
status = false
}
return status
}
```
source: https://developer.okta.com/blog/2021/02/17/building-and-securing-a-go-and-gin-web-application#how-to-validate-an-access-token-in-go
#### Test avec Postman
- Installation
- Pour installer postman j'ai utilisé la commande
```
$ sudo snap install postman
```
- Configuration
- ![](20230130060242.png)
-
- Obtention du token
- Au bas de la page se trouve un bouton "Get new access token" qui ouvre un navigateur, après avoir entré les informations de login d'un utilisateur, l'on obtient un token d'accès.
- ![](20230130060201.png)
- Ajout des droits dans le `main.go`
```go
//OKTA auth
authorization["bob.idiot@gmail.com"] = append(authorization["bob.idiot@gmail.com"], "GET")
authorization["jean.intellignet@gmail.com"] = append(authorization["jean.intellignet@gmail.com"], "GET", "POST", "DELETE", "DELETE")
authorizedOkta := r.Group("/")
authorizedOkta.GET("/students", getStudents)
authorizedOkta.GET("/student/:id", getStudentByID)
authorizedOkta.POST("/students", postStudent)
authorizedOkta.DELETE("/student/:id", deleteStudentById)
authorizedOkta.GET("/teachers", getTeachers)
authorizedOkta.GET("/teacher/:id", getTeacherById)
authorizedOkta.POST("/teachers", postTeacher)
authorizedOkta.DELETE("/teacher/:id", deleteTeacherById)
```
![](20230130071204.png)
## Gestion des données sensibles
Pour cette partie j'ai modifier mon code pour cacher les identifiants écrit en claire.
Pour ce faire j'ai créer un fichier `.env` dont on appel la correspondence comme ceci `os.Getenv("FOO)`
```.env
FOO="foo:bar"
ARI="aristote:Euclide"
```
Je n'ai pas eu le temps d'aller plus loin.
## Problèmes encontré
Lors de ce projet j'ai été confronté à plusieurs problèmes.
- Docker
- Lorsque je voulais arrêter un docker, j'obtenais une erreur qui me disait que je n'avais pas les droits nécessaires.
- Après avoir complètement désinstallé docker je l'ai réinstaller en version dektop. Ce qui semble avoir fixé mon problème.
- J'ai par la suite eu de nouveaux problèmes avec docker et j'ai donc continué le projet sans.
- Postman
- Après avoir installé l'application, au lancement j'ai obtenu une erreur qui faisait planter l'application.
- J'ai dû réinstaller l'application 2 fois et suis suivi des tutos différents pour chaque installation.
\ No newline at end of file
File added
Raport.png

1.74 MiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment