Skip to content

Commit dce0973

Browse files
authored
Example private data from backend (#10)
* add example auth-data to show in frontend * reorganize routes to leverage templating feature * organize routes into folders * address comments * fixup! address comments * oathkeeper rules * fixup! oathkeeper rules * revert namespace changes * auth.yml should be merge instead of resource * add explanation for commenting out ingress * add explanation on oathkeeper rules * comments in overlay as a guide updating the rules * default to private backend instead of public * infra to create oathkeeper proxy rules for kratos
1 parent e845889 commit dce0973

File tree

12 files changed

+240
-57
lines changed

12 files changed

+240
-57
lines changed

templates/kubernetes/base/auth.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
## Backend public endpoint
2+
# pattern: http://<proxy>/<not [/.ory/kratos and /api]>
3+
# In example this is serves the infoPanel data, and the status endpoints that don't require user auth
4+
apiVersion: oathkeeper.ory.sh/v1alpha1
5+
kind: Rule
6+
metadata:
7+
name: public-backend-endpoints
8+
spec:
9+
upstream:
10+
url: http://<% .Name %>.<% .Name %>
11+
preserveHost: true
12+
match:
13+
# url: http://<backend_service_domain>/<(?!(api|\.ory\/kratos)).*>
14+
methods:
15+
- GET
16+
- POST
17+
authenticators:
18+
- handler: noop
19+
authorizer:
20+
handler: allow
21+
mutators:
22+
- handler: noop
23+
---
24+
## Backend User-restricted endpoint
25+
# pattern: http://<proxy>//api
26+
# In example this is serves the /userInfo endpoint returning the user-session's info (user_id / email)
27+
# Note the authenticators is `cookie_session`,
28+
# oathkeeper will verify the validity of session then pass along user-id/email in the Request Header
29+
# these can be configured via infra's `oathkeeper-values.yml`
30+
apiVersion: oathkeeper.ory.sh/v1alpha1
31+
kind: Rule
32+
metadata:
33+
name: authenticated-backend-endpoints
34+
spec:
35+
upstream:
36+
preserveHost: true
37+
url: http://<% .Name %>.<% .Name %>
38+
match:
39+
# url: <backend_service_domain>/api/<.*>
40+
methods:
41+
- GET
42+
- POST
43+
authenticators:
44+
- handler: cookie_session
45+
authorizer:
46+
handler: allow
47+
mutators:
48+
- handler: id_token
49+
- handler: header

templates/kubernetes/base/kustomization.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ resources:
55
- deployment.yml
66
- service.yml
77
- cronjob.yml
8+
<%if eq (index .Params `userAuth`) "yes" %>- auth.yml
9+
<% end %>
810

911
configMapGenerator:
1012
- name: <% .Name %>-config
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
## Backend public endpoint
2+
# pattern: http://<proxy>/status/*
3+
# In example this is serves the infoPanel data, and the status endpoints that don't require user auth
4+
apiVersion: oathkeeper.ory.sh/v1alpha1
5+
kind: Rule
6+
metadata:
7+
name: public-backend-endpoints
8+
spec:
9+
match:
10+
url: http://<% index .Params `productionBackendSubdomain` %><% index .Params `productionHostRoot` %>/status/<.*>
11+
---
12+
## Backend User-restricted endpoint
13+
# pattern: http://<proxy>/<not [/.ory/kratos and /status]>
14+
# In example this is serves the /userInfo endpoint returning the user-session's info (user_id / email)
15+
# Note the authenticators is `cookie_session`,
16+
# oathkeeper will verify the validity of session then pass along user-id/email in the Request Header
17+
# these can be configured via infra's `oathkeeper-values.yml`
18+
apiVersion: oathkeeper.ory.sh/v1alpha1
19+
kind: Rule
20+
metadata:
21+
name: authenticated-backend-endpoints
22+
spec:
23+
match:
24+
url: http://<% index .Params `productionBackendSubdomain` %><% index .Params `productionHostRoot` %>/<(?!(status|\.ory\/kratos)).*>
25+

templates/kubernetes/overlays/production/kustomization.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ kind: Kustomization
33

44
patchesStrategicMerge:
55
- deployment.yml
6-
6+
<%if eq (index .Params `userAuth`) "yes" %>- auth.yml
7+
<% end %>
78
resources:
89
- ../../base
9-
- ingress.yml
10+
<%if eq (index .Params `userAuth`) "yes" %>## userAuth enabled - Oathkeeper proxies to backend instead of ingress
11+
# - ingress.yml
12+
<% else %>- ingress.yml<% end %>
1013
- pdb.yml
1114

1215
configMapGenerator:
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
## Backend public endpoint
2+
# pattern: http://<proxy>/status/*
3+
# In example this is serves the infoPanel data, and the status endpoints that don't require user auth
4+
apiVersion: oathkeeper.ory.sh/v1alpha1
5+
kind: Rule
6+
metadata:
7+
name: public-backend-endpoints
8+
spec:
9+
match:
10+
url: http://<% index .Params `stagingBackendSubdomain` %><% index .Params `stagingHostRoot` %>/status/<.*>
11+
---
12+
## Backend User-restricted endpoint
13+
# pattern: http://<proxy>//api
14+
# In example this is serves the /userInfo endpoint returning the user-session's info (user_id / email)
15+
# Note the authenticators is `cookie_session`,
16+
# oathkeeper will verify the validity of session then pass along user-id/email in the Request Header
17+
# these can be configured via infra's `oathkeeper-values.yml`
18+
apiVersion: oathkeeper.ory.sh/v1alpha1
19+
kind: Rule
20+
metadata:
21+
name: authenticated-backend-endpoints
22+
spec:
23+
match:
24+
url: http://<% index .Params `stagingBackendSubdomain` %><% index .Params `stagingHostRoot` %>/<(?!(status|\.ory\/kratos)).*>

templates/kubernetes/overlays/staging/kustomization.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ kind: Kustomization
33

44
patchesStrategicMerge:
55
- deployment.yml
6-
6+
<%if eq (index .Params `userAuth`) "yes" %>- auth.yml
7+
<% end %>
78
resources:
89
- ../../base
9-
- ingress.yml
10+
<%if eq (index .Params `userAuth`) "yes" %>## userAuth enabled - Oathkeeper proxies to backend instead of ingress
11+
# - ingress.yml
12+
<% else %>- ingress.yml<% end %>
1013

1114
configMapGenerator:
1215
- name: <% .Name %>-config

templates/src/app.js

Lines changed: 10 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,20 @@
1-
var aws = require("aws-sdk");
2-
var cfsign = require("aws-cloudfront-sign");
1+
var dotenv = require("dotenv");
32
var express = require("express");
43
var morgan = require("morgan");
54

65
var { connect } = require("./db");
7-
6+
const statusRoutes = require("./app/status");
7+
<%if eq (index .Params `fileUploads`) "yes" %>const fileRoutes = require("./app/file");
8+
<% end %><%if eq (index .Params `userAuth`) "yes" %>const authRoutes = require("./app/auth");
9+
<% end %>
10+
dotenv.config();
811
var app = express();
912
app.use(morgan("combined"));
10-
var s3 = new aws.S3();
11-
12-
app.get("/presigned/:key", (req, res) => {
13-
var params = {
14-
Bucket: process.env.S3_BUCKET,
15-
Fields: {
16-
key: req.params.key,
17-
},
18-
};
19-
20-
s3.createPresignedPost(params, (err, data) => {
21-
if (err) {
22-
console.error(err);
23-
res.sendStatus(500);
24-
} else {
25-
console.log(data);
26-
res.send(data);
27-
}
28-
});
29-
});
30-
31-
app.get("/:key", (req, res) => {
32-
var params = {
33-
keypairId: process.env.CF_KEYPAIR_ID,
34-
privateKeyString: process.env.CF_KEYPAIR_SECRET_KEY,
35-
expireTime: new Date().getTime() + 30000, // defaults to 30s
36-
};
37-
38-
var url = cfsign.getSignedUrl(
39-
`https://files.${process.env.DOMAIN}/${req.params.key}`,
40-
params
41-
);
42-
43-
console.log(url);
44-
res.redirect(url);
45-
});
46-
47-
app.get("/status/ready", (req, res) => {
48-
res.send("OK");
49-
});
50-
51-
app.get("/status/alive", (req, res) => {
52-
res.send("OK");
53-
});
54-
55-
app.get("/status/about", (req, res) => {
56-
res.send({
57-
podName: process.env.POD_NAME,
58-
});
59-
});
6013

14+
app.use("/status", statusRoutes);
15+
<%if eq (index .Params `userAuth`) "yes" %>app.use("/auth", authRoutes);
16+
<% end %><%if eq (index .Params `fileUploads`) "yes" %>app.use("/file", fileRoutes);
17+
<% end %>
6118
var port = process.env.SERVER_PORT;
6219
if (!port) {
6320
port = 3000;

templates/src/app/auth/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
var { Router } = require("express");
2+
3+
var { authMiddleware } = require("../../middleware/auth");
4+
5+
var router = Router()
6+
7+
router.get("/userInfo", authMiddleware, (req, res) => {
8+
res.json(req.user);
9+
});
10+
11+
module.exports = router;

templates/src/app/file/index.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
var { Router } = require("express");
2+
var aws = require("aws-sdk");
3+
var cfsign = require("aws-cloudfront-sign");
4+
5+
var router = Router()
6+
var s3 = new aws.S3();
7+
8+
router.get("/presigned/:key", (req, res) => {
9+
var params = {
10+
Bucket: process.env.S3_BUCKET,
11+
Fields: {
12+
key: req.params.key,
13+
},
14+
};
15+
16+
s3.createPresignedPost(params, (err, data) => {
17+
if (err) {
18+
console.error(err);
19+
res.sendStatus(500);
20+
} else {
21+
console.log(data);
22+
res.send(data);
23+
}
24+
});
25+
});
26+
27+
router.get("/:key", (req, res) => {
28+
var params = {
29+
keypairId: process.env.CF_KEYPAIR_ID,
30+
privateKeyString: process.env.CF_KEYPAIR_SECRET_KEY,
31+
expireTime: new Date().getTime() + 30000, // defaults to 30s
32+
};
33+
34+
var url = cfsign.getSignedUrl(
35+
`https://files.${process.env.DOMAIN}/${req.params.key}`,
36+
params
37+
);
38+
39+
console.log(url);
40+
res.redirect(url);
41+
});
42+
43+
module.exports = router;

templates/src/app/status/index.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
var { Router } = require("express");
2+
3+
var router = Router()
4+
5+
router.get("/ready", (req, res) => {
6+
res.send("OK");
7+
});
8+
9+
router.get("/alive", (req, res) => {
10+
res.send("OK");
11+
});
12+
13+
router.get("/about", (req, res) => {
14+
res.send({
15+
podName: process.env.POD_NAME,
16+
});
17+
});
18+
19+
module.exports = router;

0 commit comments

Comments
 (0)