SLIDE 67: Section: Security in Production
Protecting Your System and Users
#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4{font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;fill:#000000;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .error-icon{fill:#552222;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .error-text{fill:#552222;stroke:#552222;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .edge-thickness-normal{stroke-width:1px;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .marker{fill:#666;stroke:#666;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .marker.cross{stroke:#666;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 svg{font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 p{margin:0;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .label{font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";color:#000000;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .cluster-label text{fill:#333;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .cluster-label span{color:#333;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .cluster-label span p{background-color:transparent;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .label text,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 span{fill:#000000;color:#000000;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .node rect,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .node circle,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .node ellipse,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .node polygon,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .node path{fill:#eee;stroke:#999;stroke-width:1px;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .rough-node .label text,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .node .label text,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .image-shape .label,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .icon-shape .label{text-anchor:middle;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .rough-node .label,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .node .label,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .image-shape .label,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .icon-shape .label{text-align:center;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .node.clickable{cursor:pointer;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .root .anchor path{fill:#666!important;stroke-width:0;stroke:#666;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .arrowheadPath{fill:#333333;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .edgePath .path{stroke:#666;stroke-width:1px;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .flowchart-link{stroke:#666;fill:none;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .edgeLabel{background-color:white;text-align:center;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .edgeLabel p{background-color:white;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .edgeLabel rect{opacity:0.5;background-color:white;fill:white;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .labelBkg{background-color:rgba(255, 255, 255, 0.5);}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .cluster rect{fill:hsl(0, 0%, 98.9215686275%);stroke:#707070;stroke-width:1px;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .cluster text{fill:#333;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .cluster span{color:#333;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:12px;background:hsl(-160, 0%, 93.3333333333%);border:1px solid #707070;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#000000;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 rect.text{fill:none;stroke-width:0;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .icon-shape,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .image-shape{background-color:white;text-align:center;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .icon-shape p,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .image-shape p{background-color:white;padding:2px;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .icon-shape .label rect,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .image-shape .label rect{opacity:0.5;background-color:white;fill:white;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 .node .neo-node{stroke:#999;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 [data-look="neo"].node rect,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 [data-look="neo"].cluster rect,#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 [data-look="neo"].node polygon{stroke:url(#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 [data-look="neo"].swimlane.cluster rect{filter:none;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 [data-look="neo"].node path{stroke:url(#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4-gradient);stroke-width:1px;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 [data-look="neo"].node .neo-line path{stroke:#999;filter:none;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 [data-look="neo"].node circle{stroke:url(#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 [data-look="neo"].node circle .state-start{fill:#000000;}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 [data-look="neo"].icon-shape .icon{fill:url(#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 [data-look="neo"].icon-shape .icon-neo path{stroke:url(#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-5f7ec9c9-c4c7-4ff8-a24a-10cdffd548b4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}AuthenticationAuthorizationSecrets ManagementNetwork SecurityData Protection
Security Mindset:
Key Insight:
Security is not a feature. It is a property of the system. Every design decision has security implications.
SLIDE 68: Authentication: Token-Based Auth
How Modern Auth Works
JWT (JSON Web Token) Flow:
#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a{font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;fill:#000000;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .error-icon{fill:#552222;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .error-text{fill:#552222;stroke:#552222;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .edge-thickness-normal{stroke-width:1px;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .edge-thickness-thick{stroke-width:3.5px;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .edge-pattern-solid{stroke-dasharray:0;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .marker{fill:#666;stroke:#666;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .marker.cross{stroke:#666;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a svg{font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a p{margin:0;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .label{font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";color:#000000;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .cluster-label text{fill:#333;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .cluster-label span{color:#333;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .cluster-label span p{background-color:transparent;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .label text,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a span{fill:#000000;color:#000000;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .node rect,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .node circle,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .node ellipse,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .node polygon,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .node path{fill:#eee;stroke:#999;stroke-width:1px;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .rough-node .label text,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .node .label text,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .image-shape .label,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .icon-shape .label{text-anchor:middle;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .rough-node .label,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .node .label,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .image-shape .label,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .icon-shape .label{text-align:center;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .node.clickable{cursor:pointer;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .root .anchor path{fill:#666!important;stroke-width:0;stroke:#666;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .arrowheadPath{fill:#333333;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .edgePath .path{stroke:#666;stroke-width:1px;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .flowchart-link{stroke:#666;fill:none;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .edgeLabel{background-color:white;text-align:center;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .edgeLabel p{background-color:white;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .edgeLabel rect{opacity:0.5;background-color:white;fill:white;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .labelBkg{background-color:rgba(255, 255, 255, 0.5);}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .cluster rect{fill:hsl(0, 0%, 98.9215686275%);stroke:#707070;stroke-width:1px;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .cluster text{fill:#333;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .cluster span{color:#333;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:12px;background:hsl(-160, 0%, 93.3333333333%);border:1px solid #707070;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#000000;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a rect.text{fill:none;stroke-width:0;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .icon-shape,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .image-shape{background-color:white;text-align:center;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .icon-shape p,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .image-shape p{background-color:white;padding:2px;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .icon-shape .label rect,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .image-shape .label rect{opacity:0.5;background-color:white;fill:white;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a .node .neo-node{stroke:#999;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a [data-look="neo"].node rect,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a [data-look="neo"].cluster rect,#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a [data-look="neo"].node polygon{stroke:url(#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a [data-look="neo"].swimlane.cluster rect{filter:none;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a [data-look="neo"].node path{stroke:url(#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a-gradient);stroke-width:1px;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a [data-look="neo"].node .neo-line path{stroke:#999;filter:none;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a [data-look="neo"].node circle{stroke:url(#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a [data-look="neo"].node circle .state-start{fill:#000000;}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a [data-look="neo"].icon-shape .icon{fill:url(#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a [data-look="neo"].icon-shape .icon-neo path{stroke:url(#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-b735447a-b5d8-419e-ad91-888d69fcb65a :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}User LoginAuth ServerJWT IssuedUser Stores JWTRequests with JWTService Validates JWT
JWT Structure:
Header.Payload.Signature
eyJhbGciOiJIUzI1NiJ9. # Header: algorithm
eyJ1c2VyX2lkIjoxMjM0NX0. # Payload: claims
SflKxwRJSMeKKF2QT4fwpM # Signature: verification
JWT Payload Example:
{
"sub": "user_12345",
"email": "user@example.com",
"roles": ["user", "admin"],
"iat": 1705315200,
"exp": 1705318800
}
SLIDE 69: Authentication: Token-Based Auth (continued)
JWT Best Practices:
Refresh Token Flow:
def login(username, password):
user = authenticate(username, password)
access_token = create_jwt(
user_id=user.id,
expires_in=timedelta(minutes=15)
)
refresh_token = create_refresh_token(
user_id=user.id,
expires_in=timedelta(days=7)
)
# Store refresh token hash in database
store_refresh_token(user.id, hash(refresh_token))
return {
"access_token": access_token,
"refresh_token": refresh_token
}
SLIDE 70: Authentication: Token-Based Auth (continued)
Token Refresh Implementation:
def refresh_access_token(refresh_token):
# Validate refresh token
payload = decode_refresh_token(refresh_token)
user_id = payload["user_id"]
# Check if refresh token is valid in database
stored_hash = get_stored_refresh_token(user_id)
if stored_hash != hash(refresh_token):
raise InvalidRefreshTokenError()
# Check if refresh token is revoked
if is_token_revoked(refresh_token):
raise TokenRevokedError()
# Issue new access token
access_token = create_jwt(
user_id=user_id,
expires_in=timedelta(minutes=15)
)
return {"access_token": access_token}
Token Revocation:
def logout(user_id, refresh_token):
# Add to revocation list
revoke_token(refresh_token)
# Remove from valid tokens
delete_refresh_token(user_id)
SLIDE 71: Authorization: RBAC and ABAC
Controlling What Users Can Do
Role-Based Access Control (RBAC):
ROLES = {
"admin": ["read", "write", "delete", "manage_users"],
"editor": ["read", "write"],
"viewer": ["read"],
}
def check_permission(user, action, resource):
user_role = get_user_role(user.id)
allowed_actions = ROLES.get(user_role, [])
if action not in allowed_actions:
raise PermissionDeniedError()
Attribute-Based Access Control (ABAC):
def check_permission(user, action, resource):
# Check multiple attributes
rules = [
user.department == resource.department,
user.clearance_level >= resource.classification,
action in user.allowed_actions,
not resource.is_archived or user.can_access_archived,
]
if not all(rules):
raise PermissionDeniedError()
SLIDE 72: Authorization: RBAC and ABAC (continued)
Comparison:
Resource-Level Permissions:
def can_edit_document(user, document):
# Owner can always edit
if document.owner_id == user.id:
return True
# Check explicit share
share = get_share(document.id, user.id)
if share and share.permission in ["edit", "admin"]:
return True
# Check team access
if document.team_id in user.team_ids:
team_permission = get_team_permission(document.team_id)
if team_permission in ["edit", "admin"]:
return True
return False
SLIDE 73: Secrets Management: Principles
Handling Sensitive Configuration
What Are Secrets:
Secrets Anti-Patterns:
# Bad: Hardcoded secrets
DATABASE_URL = "postgres://user:password123@db.example.com/mydb"
API_KEY = "sk_live_abc123def456"
# Bad: Secrets in git
# .env file committed to repository
# Bad: Secrets in logs
logger.info(f"Connecting with{connection_string}")
SLIDE 74: Secrets Management: Implementation
Environment Variables (Basic):
import os
DATABASE_URL = os.environ["DATABASE_URL"]
API_KEY = os.environ["API_KEY"]
# Kubernetes secret mounted as env var
# kubectl create secret generic myapp-secrets \
# --from-literal=DATABASE_URL=postgres://... \
# --from-literal=API_KEY=sk_live_...
Secrets Manager (Production):
import boto3
def get_secret(secret_name):
client = boto3.client("secretsmanager")
response = client.get_secret_value(SecretId=secret_name)
return json.loads(response["SecretString"])
# Usage
secrets = get_secret("myapp/production")
database_url = secrets["database_url"]
api_key = secrets["api_key"]
SLIDE 75: Secrets Management: Implementation (continued)
HashiCorp Vault Integration:
import hvac
class VaultClient:
def __init__(self):
self.client = hvac.Client(
url=os.environ["VAULT_ADDR"],
token=os.environ["VAULT_TOKEN"]
)
def get_secret(self, path):
response = self.client.secrets.kv.v2.read_secret_version(
path=path
)
return response["data"]["data"]
def get_database_credentials(self):
# Dynamic secrets: Vault generates temporary credentials
response = self.client.secrets.database.generate_credentials(
name="myapp-db-role"
)
return {
"username": response["data"]["username"],
"password": response["data"]["password"],
"ttl": response["lease_duration"]
}
Dynamic Secrets Benefits:
SLIDE 76: Secrets Management: Rotation
Changing Secrets Without Downtime
Secret Rotation Process:
#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831{font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;fill:#000000;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .error-icon{fill:#552222;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .error-text{fill:#552222;stroke:#552222;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .edge-thickness-normal{stroke-width:1px;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .marker{fill:#666;stroke:#666;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .marker.cross{stroke:#666;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 svg{font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 p{margin:0;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .label{font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";color:#000000;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .cluster-label text{fill:#333;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .cluster-label span{color:#333;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .cluster-label span p{background-color:transparent;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .label text,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 span{fill:#000000;color:#000000;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .node rect,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .node circle,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .node ellipse,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .node polygon,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .node path{fill:#eee;stroke:#999;stroke-width:1px;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .rough-node .label text,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .node .label text,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .image-shape .label,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .icon-shape .label{text-anchor:middle;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .rough-node .label,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .node .label,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .image-shape .label,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .icon-shape .label{text-align:center;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .node.clickable{cursor:pointer;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .root .anchor path{fill:#666!important;stroke-width:0;stroke:#666;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .arrowheadPath{fill:#333333;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .edgePath .path{stroke:#666;stroke-width:1px;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .flowchart-link{stroke:#666;fill:none;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .edgeLabel{background-color:white;text-align:center;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .edgeLabel p{background-color:white;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .edgeLabel rect{opacity:0.5;background-color:white;fill:white;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .labelBkg{background-color:rgba(255, 255, 255, 0.5);}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .cluster rect{fill:hsl(0, 0%, 98.9215686275%);stroke:#707070;stroke-width:1px;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .cluster text{fill:#333;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .cluster span{color:#333;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:12px;background:hsl(-160, 0%, 93.3333333333%);border:1px solid #707070;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#000000;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 rect.text{fill:none;stroke-width:0;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .icon-shape,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .image-shape{background-color:white;text-align:center;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .icon-shape p,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .image-shape p{background-color:white;padding:2px;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .icon-shape .label rect,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .image-shape .label rect{opacity:0.5;background-color:white;fill:white;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 .node .neo-node{stroke:#999;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 [data-look="neo"].node rect,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 [data-look="neo"].cluster rect,#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 [data-look="neo"].node polygon{stroke:url(#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 [data-look="neo"].swimlane.cluster rect{filter:none;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 [data-look="neo"].node path{stroke:url(#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831-gradient);stroke-width:1px;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 [data-look="neo"].node .neo-line path{stroke:#999;filter:none;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 [data-look="neo"].node circle{stroke:url(#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 [data-look="neo"].node circle .state-start{fill:#000000;}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 [data-look="neo"].icon-shape .icon{fill:url(#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 [data-look="neo"].icon-shape .icon-neo path{stroke:url(#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-b853125c-5cd0-4c06-82d9-f41e36c83831 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}Generate New SecretDeploy with BothVerify New WorksRemove Old Secret
Implementation:
class RotatableSecret:
def __init__(self, secret_name):
self.secret_name = secret_name
self.current = None
self.previous = None
self.last_refresh = None
def refresh(self):
secrets = vault.get_secret(self.secret_name)
self.previous = self.current
self.current = secrets["current"]
self.last_refresh = time.time()
def validate(self, provided_key):
# Accept both current and previous during rotation
return provided_key in [self.current, self.previous]
api_key = RotatableSecret("myapp/api_key")
# Periodic refresh
scheduler.every(1).hour.do(api_key.refresh)
SLIDE 77: Network Security: Defense in Depth
Multiple Layers of Protection
#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6{font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;fill:#000000;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .error-icon{fill:#552222;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .error-text{fill:#552222;stroke:#552222;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .edge-thickness-normal{stroke-width:1px;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .marker{fill:#666;stroke:#666;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .marker.cross{stroke:#666;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 svg{font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 p{margin:0;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .label{font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";color:#000000;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .cluster-label text{fill:#333;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .cluster-label span{color:#333;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .cluster-label span p{background-color:transparent;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .label text,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 span{fill:#000000;color:#000000;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .node rect,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .node circle,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .node ellipse,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .node polygon,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .node path{fill:#eee;stroke:#999;stroke-width:1px;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .rough-node .label text,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .node .label text,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .image-shape .label,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .icon-shape .label{text-anchor:middle;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .rough-node .label,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .node .label,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .image-shape .label,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .icon-shape .label{text-align:center;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .node.clickable{cursor:pointer;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .root .anchor path{fill:#666!important;stroke-width:0;stroke:#666;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .arrowheadPath{fill:#333333;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .edgePath .path{stroke:#666;stroke-width:1px;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .flowchart-link{stroke:#666;fill:none;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .edgeLabel{background-color:white;text-align:center;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .edgeLabel p{background-color:white;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .edgeLabel rect{opacity:0.5;background-color:white;fill:white;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .labelBkg{background-color:rgba(255, 255, 255, 0.5);}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .cluster rect{fill:hsl(0, 0%, 98.9215686275%);stroke:#707070;stroke-width:1px;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .cluster text{fill:#333;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .cluster span{color:#333;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Display","Segoe UI",Helvetica,"Apple Color Emoji","Noto Sans Arabic","Noto Sans Hebrew",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:12px;background:hsl(-160, 0%, 93.3333333333%);border:1px solid #707070;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#000000;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 rect.text{fill:none;stroke-width:0;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .icon-shape,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .image-shape{background-color:white;text-align:center;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .icon-shape p,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .image-shape p{background-color:white;padding:2px;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .icon-shape .label rect,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .image-shape .label rect{opacity:0.5;background-color:white;fill:white;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 .node .neo-node{stroke:#999;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 [data-look="neo"].node rect,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 [data-look="neo"].cluster rect,#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 [data-look="neo"].node polygon{stroke:url(#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 [data-look="neo"].swimlane.cluster rect{filter:none;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 [data-look="neo"].node path{stroke:url(#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6-gradient);stroke-width:1px;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 [data-look="neo"].node .neo-line path{stroke:#999;filter:none;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 [data-look="neo"].node circle{stroke:url(#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 [data-look="neo"].node circle .state-start{fill:#000000;}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 [data-look="neo"].icon-shape .icon{fill:url(#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 [data-look="neo"].icon-shape .icon-neo path{stroke:url(#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-5b8f2241-136f-4469-92bd-103bbf7a95d6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}InternetWAFLoad BalancerAPI GatewayService MeshApplicationDatabase
Security Layers:
SLIDE 78: Network Security: Zero Trust
Never Trust, Always Verify
Traditional Security (Perimeter):
Inside network = trusted
Outside network = untrusted
Problem: Once attacker is inside, they have access to everything.
Zero Trust Security:
Trust nothing by default
Verify every request
Assume breach has occurred
Zero Trust Principles:
SLIDE 79: Network Security: Zero Trust (continued)
Service-to-Service Authentication (mTLS):
# Istio mTLS configuration
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: production
spec:
mtls:
mode: STRICT # Require mTLS for all traffic
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: order-service-policy
namespace: production
spec:
selector:
matchLabels:
app: order-service
rules:
-from:
-source:
principals:["cluster.local/ns/production/sa/api-gateway"]
to:
-operation:
methods:["GET","POST"]
paths:["/orders/*"]
Only api-gateway service account can call order-service.
SLIDE 80: Network Security: Network Policies
Controlling Traffic Flow
Default Deny:
# Deny all ingress by default
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector:{}
policyTypes:
- Ingress
Allow Specific Traffic:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-to-database
namespace: production
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
-from:
-podSelector:
matchLabels:
app: api-server
ports:
-protocol: TCP
port:5432
SLIDE 81: Data Protection: Encryption
Protecting Data at Rest and in Transit
Encryption Types:
TLS Configuration:
# Good TLS configuration
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2
ssl_context.set_ciphers(
"ECDHE+AESGCM:DHE+AESGCM:ECDHE+CHACHA20:DHE+CHACHA20"
)
ssl_context.load_cert_chain("cert.pem", "key.pem")
Database Encryption:
-- PostgreSQL: Enable encryption for column
CREATE EXTENSION pgcrypto;
-- Encrypt sensitive data
INSERT INTO users (email, ssn_encrypted)
VALUES (
'user@example.com',
pgp_sym_encrypt('123-45-6789', 'encryption_key')
);
SLIDE 82: Data Protection: PII Handling
Protecting Personal Information
PII Categories:
PII Protection Strategies:
# Tokenization: Replace PII with token
def tokenize_ssn(ssn):
token = generate_token()
secure_store.save(token, encrypt(ssn))
return token
# Masking: Show partial data
def mask_credit_card(card_number):
return f"****-****-****-{card_number[-4:]}"
# Anonymization: Remove identifying info
def anonymize_user(user):
return {
"age_group": get_age_group(user.birth_date),
"region": get_region(user.zip_code),
"purchase_count": user.purchase_count
}
SLIDE 83: Data Protection: PII Handling (continued)
Data Retention Policies:
class DataRetention:
POLICIES = {
"user_sessions": timedelta(days=30),
"audit_logs": timedelta(days=365),
"payment_records": timedelta(days=7*365), # 7 years
"deleted_user_data": timedelta(days=30), # GDPR
}
def cleanup_expired_data(self):
for data_type, retention in self.POLICIES.items():
cutoff = datetime.now() - retention
self.delete_older_than(data_type, cutoff)
# Scheduled job
scheduler.daily(DataRetention().cleanup_expired_data)
GDPR Compliance:
SLIDE 84: API Security: Rate Limiting
Preventing Abuse
Why Rate Limit:
Without rate limiting:
- Single user can overwhelm system
- Credential stuffing attacks succeed
- API abuse goes unchecked
- Costs spiral out of control
Rate Limiting Implementation:
from redis import Redis
class RateLimiter:
def __init__(self, redis_client, limit, window_seconds):
self.redis = redis_client
self.limit = limit
self.window = window_seconds
def is_allowed(self, key):
current = self.redis.incr(key)
if current == 1:
self.redis.expire(key, self.window)
return current <= self.limit
# 100 requests per minute per user
limiter = RateLimiter(redis, limit=100, window_seconds=60)
def handle_request(request):
key = f"rate_limit:{request.user_id}"
if not limiter.is_allowed(key):
return Response(
status=429,
headers={"Retry-After": "60"},
body={"error": "Rate limit exceeded"}
)
return process_request(request)
SLIDE 85: API Security: Rate Limiting (continued)
Tiered Rate Limits:
Rate Limit Headers:
def add_rate_limit_headers(response, key):
info = limiter.get_info(key)
response.headers["X-RateLimit-Limit"] = str(info.limit)
response.headers["X-RateLimit-Remaining"] = str(info.remaining)
response.headers["X-RateLimit-Reset"] = str(info.reset_time)
return response
Different Limits for Different Endpoints:
RATE_LIMITS = {
"/api/login": {"limit": 5, "window": 60}, # Prevent brute force
"/api/search": {"limit": 30, "window": 60}, # Expensive operation
"/api/users": {"limit": 100, "window": 60}, # Standard CRUD
}
SLIDE 86: API Security: Input Validation
Never Trust User Input
Common Vulnerabilities:
Input Validation:
from pydantic import BaseModel, validator, constr
import re
class CreateUserRequest(BaseModel):
email: constr(max_length=255)
username: constr(min_length=3, max_length=50, regex=r'^[a-zA-Z0-9_]+$')
age: int
@validator('email')
def validate_email(cls, v):
if not re.match(r'^[\w\.-]+@[\w\.-]+\.\w+$', v):
raise ValueError('Invalid email format')
return v.lower()
@validator('age')
def validate_age(cls, v):
if v < 0 or v > 150:
raise ValueError('Age must be between 0 and 150')
return v
SLIDE 87: API Security: Input Validation (continued)
SQL Injection Prevention:
XSS Prevention:
import html
# Bad: Direct output
def render_comment(comment):
return f"<div>{comment}</div>"
# Input: <script>steal(document.cookie)</script>
# Good: HTML escape
def render_comment(comment):
return f"<div>{html.escape(comment)}</div>"
# Output: <script>steal(document.cookie)</script>
SLIDE 88: Security: Audit Logging
Recording Security-Relevant Events
What to Log:
Audit Log Implementation:
class AuditLog:
def log(self, event_type, user_id, details):
entry = {
"timestamp": datetime.utcnow().isoformat(),
"event_type": event_type,
"user_id": user_id,
"ip_address": get_client_ip(),
"user_agent": get_user_agent(),
"details": details,
"trace_id": get_trace_id(),
}
# Write to immutable audit store
self.audit_store.append(entry)
# Alert on suspicious activity
if self.is_suspicious(entry):
self.alert_security_team(entry)
SLIDE 89: Security: Audit Logging (continued)
Suspicious Activity Detection:
class SecurityMonitor:
def check_login_patterns(self, user_id, ip_address):
# Multiple failed logins
recent_failures = self.get_recent_failures(user_id, minutes=15)
if len(recent_failures) >= 5:
self.alert("Possible brute force", user_id=user_id)
self.block_temporarily(user_id)
# Login from new location
known_ips = self.get_user_known_ips(user_id)
if ip_address not in known_ips:
self.alert("Login from new location",
user_id=user_id,
ip=ip_address)
# Impossible travel
last_login = self.get_last_login(user_id)
if last_login:
distance = geo_distance(last_login.ip, ip_address)
time_diff = time.now() - last_login.timestamp
if distance / time_diff.hours > 500: # > 500 mph
self.alert("Impossible travel detected",
user_id=user_id)
SLIDE 90: Security: Anti-Patterns
Common Security Mistakes
Anti-Pattern 1: Security by Obscurity
# Bad: Hidden endpoint is "secure"
@app.get("/admin-panel-xyz123") # "Nobody will guess this URL"
def admin_panel():
return admin_data
# Good: Proper authentication
@app.get("/admin")
@require_role("admin")
def admin_panel():
return admin_data
Anti-Pattern 2: Trusting Client-Side Validation
# Bad: Only client-side price check
# Client sends: {"item_id": 123, "price": 0.01}
def purchase(request):
charge_card(request.price) # User set their own price!
# Good: Server-side validation
def purchase(request):
item = get_item(request.item_id)
charge_card(item.price) # Use server-side price
SLIDE 91: Security: Anti-Patterns (continued)
Anti-Pattern 3: Overly Permissive CORS
# Bad: Allow all origins
@app.after_request
def add_cors(response):
response.headers["Access-Control-Allow-Origin"] = "*"
return response
# Good: Specific allowed origins
ALLOWED_ORIGINS = ["https://myapp.com", "https://admin.myapp.com"]
@app.after_request
def add_cors(response):
origin = request.headers.get("Origin")
if origin in ALLOWED_ORIGINS:
response.headers["Access-Control-Allow-Origin"] = origin
return response
Anti-Pattern 4: Logging Sensitive Data
# Bad: Logging credentials
logger.info(f"User login attempt:{username},{password}")
# Good: Never log sensitive data
logger.info(f"User login attempt:{username}")
SLIDE 92: Security: Summary
Key Takeaways
Authentication:
- Use short-lived JWTs with refresh tokens
- Store tokens securely (httpOnly cookies)
- Implement proper logout (token revocation)
Authorization:
- Use RBAC for most applications
- Check permissions at resource level
- Principle of least privilege
Secrets Management:
- Never hardcode secrets
- Use secrets manager (Vault, AWS Secrets Manager)
- Rotate secrets regularly
- Use dynamic secrets when possible
SLIDE 93: Security: Summary (continued)
Network Security:
- Zero trust: verify every request
- mTLS for service-to-service
- Network policies: default deny
- WAF for external traffic
Data Protection:
- Encrypt in transit and at rest
- Handle PII carefully
- Implement data retention policies
- Support GDPR rights
API Security:
- Rate limiting at multiple levels
- Input validation on server side
- Parameterized queries
- Comprehensive audit logging
Coming Up Next: Section: Cost Optimization