Keep it Secret, Keep it Safe - Docker Secrets and DI

@danaluther
Keep it Secret, Keep it Safe
Docker Secrets and DI (Containers)
https://joind.in/talk/78c5b
https://github.com/DanaLuther/kiskis
@danaluther
What are we keeping secret?
All the things? (no… but de
fi
nitely the important things)
@danaluther
What are we keeping secret?
All the things? (no… but de
fi
nitely the important things)
• File Based Credentials
@danaluther
What are we keeping secret?
All the things? (no… but de
fi
nitely the important things)
• File Based Credentials
• SSH key
fi
les
@danaluther
What are we keeping secret?
All the things? (no… but de
fi
nitely the important things)
• File Based Credentials
• SSH key
fi
les
• Json auth
fi
les
@danaluther
What are we keeping secret?
All the things? (no… but de
fi
nitely the important things)
• File Based Credentials
• SSH key
fi
les
• Json auth
fi
les
• Variable Credentials
@danaluther
What are we keeping secret?
All the things? (no… but de
fi
nitely the important things)
• File Based Credentials
• SSH key
fi
les
• Json auth
fi
les
• Variable Credentials
• API keys and tokens
@danaluther
What are we keeping secret?
All the things? (no… but de
fi
nitely the important things)
• File Based Credentials
• SSH key
fi
les
• Json auth
fi
les
• Variable Credentials
• API keys and tokens
• Any value that could compromise security / grant access to your data or
accounts.
@danaluther
Isn't it already safe?
…Ish. It depends - how are you storing it currently?
@danaluther
Isn't it already safe?
…Ish. It depends - how are you storing it currently?
• Storing credentials directly into a repo
@danaluther
Isn't it already safe?
…Ish. It depends - how are you storing it currently?
• Storing credentials directly into a repo
• Readable by anyone with access to that repo
@danaluther
Isn't it already safe?
…Ish. It depends - how are you storing it currently?
• Storing credentials directly into a repo
• Readable by anyone with access to that repo
• Exposed in coverage reports or anything that includes the source code in
analysis or reporting displays
@danaluther
Isn't it already safe?
…Ish. It depends - how are you storing it currently?
• Storing credentials directly into a repo
• Readable by anyone with access to that repo
• Exposed in coverage reports or anything that includes the source code in
analysis or reporting displays
• Storing credentials in ENV variables
@danaluther
Isn't it already safe?
…Ish. It depends - how are you storing it currently?
• Storing credentials directly into a repo
• Readable by anyone with access to that repo
• Exposed in coverage reports or anything that includes the source code in
analysis or reporting displays
• Storing credentials in ENV variables
• Exposed via phpinfo, server dumps, or to anyone who has compromised
the server
@danaluther
Isn't it already safe?
…Ish. It depends - how are you storing it currently?
• Storing credentials directly into a repo
• Readable by anyone with access to that repo
• Exposed in coverage reports or anything that includes the source code in
analysis or reporting displays
• Storing credentials in ENV variables
• Exposed via phpinfo, server dumps, or to anyone who has compromised
the server
• Not static and has the potential to be modi
fi
ed nefariously
@danaluther
Does it really matter?
I don’t know … does it?
@danaluther
Does it really matter?
I don’t know … does it?
• How important is the service or information being used?
@danaluther
Does it really matter?
I don’t know … does it?
• How important is the service or information being used?
• How big is the impact if that service is accessed by another?
@danaluther
Does it really matter?
I don’t know … does it?
• How important is the service or information being used?
• How big is the impact if that service is accessed by another?
• Is the credential the sole key to access, or is does the service have additional
factors in play?
@danaluther
Does it really matter?
I don’t know … does it?
• How important is the service or information being used?
• How big is the impact if that service is accessed by another?
• Is the credential the sole key to access, or is does the service have additional
factors in play?
• What is the risk level compared to the technical debt?
@danaluther
Does it really matter?
I don’t know … does it?
• How important is the service or information being used?
• How big is the impact if that service is accessed by another?
• Is the credential the sole key to access, or is does the service have additional
factors in play?
• What is the risk level compared to the technical debt?
• Does the information get published into your application as part of the public
UI?
@danaluther
Sample API Object
Class with public API credential property
class SampleObject


{


	
public string $myApiKey = 'ABC1234';


	
public function connect()


	
{


	
	
/
/
Do something with $myApiKey here


	
}


}
@danaluther
Sample API Object
Class with public API credential property
class SampleObject


{


	
public string $myApiKey = 'ABC1234';


	
public function connect()


	
{


	
	
/
/
Do something with $myApiKey here


	
}


}


new ExampleSampleObject()
@danaluther
Sample API Object v2
Class with API credential property
class SampleObjectMoreSecure


{


	
private string $myApiKey = 'ABC1234';


	
public function connect()


	
{


	
	
/
/
Do something with $myApiKey here


	
}


}
@danaluther
Sample API Object v2
Class with API credential property
class SampleObjectMoreSecure


{


	
private string $myApiKey = 'ABC1234';


	
public function connect()


	
{


	
	
/
/
Do something with $myApiKey here


	
}


}


new ExampleSampleObjectMoreSecure()
@danaluther
Sample API Object v3
Class with constructed private API credential property
class SampleObjectConstructed


{


	
private string $_myApiKey;


	
public function __construct(string $apiKey)


	
{


	
	
$this
-
>
_myApiKey = $apiKey;


	
}


	
public function connect()


	
{


	
	
/
/
Do something


	
}


}
@danaluther
Sample API Object v3
Class with constructed private API credential property
class SampleObjectConstructed


{


	
private string $_myApiKey;


	
public function __construct(string $apiKey)


	
{


	
	
$this
-
>
_myApiKey = $apiKey;


	
}


	
public function connect()


	
{


	
	
/
/
Do something


	
}


}
new ExampleSampleObjectConstructed('Someothervalue')
@danaluther
Sample API Object v3 with $_ENV
Class with constructed private API credential property
class SampleObjectConstructed


{


	
private string $_myApiKey;


	
public function __construct(string $apiKey)


	
{


	
	
$this
-
>
_myApiKey = $apiKey;


	
}


	
public function connect()


	
{


	
	
/
/
Do something


	
}


}
@danaluther
Sample API Object v3 with $_ENV
Class with constructed private API credential property
class SampleObjectConstructed


{


	
private string $_myApiKey;


	
public function __construct(string $apiKey)


	
{


	
	
$this
-
>
_myApiKey = $apiKey;


	
}


	
public function connect()


	
{


	
	
/
/
Do something


	
}


}
new ExampleSampleObjectConstructed($_ENV['MY_SECRET_KEY'])
@danaluther
Sample API Object v3 with $_ENV
Class with constructed private API credential property
class SampleObjectConstructed


{


	
private string $_myApiKey;


	
public function __construct(string $apiKey)


	
{


	
	
$this
-
>
_myApiKey = $apiKey;


	
}


	
public function connect()


	
{


	
	
/
/
Do something


	
}


}
new ExampleSampleObjectConstructed($_ENV['MY_SECRET_KEY'])
@danaluther
Dependency Injection Containers
So, what is it and how does it help us??
@danaluther
Dependency Injection Containers
So, what is it and how does it help us??
• Does NOT help to solve the issue of
fi
le based credentials.
@danaluther
Dependency Injection Containers
So, what is it and how does it help us??
• Does NOT help to solve the issue of
fi
le based credentials.
• Does help to solve the issue of class based or variable credential strings.
@danaluther
Dependency Injection Containers
So, what is it and how does it help us??
• Does NOT help to solve the issue of
fi
le based credentials.
• Does help to solve the issue of class based or variable credential strings.
• Creates a map that de
fi
nes the default properties to be assigned to an object
when that object is created via the container.
@danaluther
Don’t reinvent the wheel.
https://packagist.org
@danaluther
Add your DI package to composer
composer.json
{


"require": {


"yiisoft/di": "^3.0.x
-
dev",


"yiisoft/injector": "^1.0",


"yiisoft/definitions": "^3.0.x
-
dev"


}


}
@danaluther
Install the composer packages
docker run --rm -v $PWD:/app composer update
https://hub.docker.com/_/composer
@danaluther
Sample API Object v3 with $_ENV via DI
Constructor moved to DI Container
require 'vendor/autoload.php';


use YiisoftDiContainer;


$container = new Container([


ExampleSampleObjectConstructed
:
:
class
=
>
[


	
'class'
=
>
ExampleSampleObjectConstructed
:
:
class,


	
'__construct()'
=
>
[$_ENV['MY_SECRET_KEY']]


],


]);
@danaluther
Sample API Object v3 with $_ENV via DI
Constructor moved to DI Container
require 'vendor/autoload.php';


use YiisoftDiContainer;


$container = new Container([


ExampleSampleObjectConstructed
:
:
class
=
>
[


	
'class'
=
>
ExampleSampleObjectConstructed
:
:
class,


	
'__construct()'
=
>
[$_ENV['MY_SECRET_KEY']]


],


]);
@danaluther
Sample API Object v3 with $_ENV via DI
Constructor moved to DI Container
require 'vendor/autoload.php';


use YiisoftDiContainer;


$container = new Container([


ExampleSampleObjectConstructed
:
:
class
=
>
[


	
'class'
=
>
ExampleSampleObjectConstructed
:
:
class,


	
'__construct()'
=
>
[$_ENV['MY_SECRET_KEY']]


],


]); $container
-
>
get(ExampleSampleObjectConstructed
:
:
class)
@danaluther
But is it secret? Is it safe?
Lets check those $_ENV vars …
@danaluther
But is it secret? Is it safe?
Lets check those $_ENV vars …
@danaluther
Docker Secrets
What are they and how do they help us?
@danaluther
Docker Secrets
What are they and how do they help us?
• Does help to solve the issue of
fi
le based credentials.
@danaluther
Docker Secrets
What are they and how do they help us?
• Does help to solve the issue of
fi
le based credentials.
• Does help to solve the issue of class based or variable credential strings.
@danaluther
Docker Secrets
What are they and how do they help us?
• Does help to solve the issue of
fi
le based credentials.
• Does help to solve the issue of class based or variable credential strings.
• Created as elements of a Docker stack and written to read-only
fi
les in the
container they are attached to.
@danaluther
Docker Secrets
What are they and how do they help us?
• Does help to solve the issue of
fi
le based credentials.
• Does help to solve the issue of class based or variable credential strings.
• Created as elements of a Docker stack and written to read-only
fi
les in the
container they are attached to.
• Can only be be modi
fi
ed by the stack when a new container is created.
@danaluther
Docker Secrets
What are they and how do they help us?
• Does help to solve the issue of
fi
le based credentials.
• Does help to solve the issue of class based or variable credential strings.
• Created as elements of a Docker stack and written to read-only
fi
les in the
container they are attached to.
• Can only be be modi
fi
ed by the stack when a new container is created.
• Cannot be exposed through inspection via the stack or parent machine. Only
visible in the container where it has been mounted.
@danaluther
What is Docker?
(Jumped ahead there didn’t I…)
https://www.docker.com
@danaluther
What is Docker?
Docker Hierarchy
https://hub.docker.com
@danaluther
What is Docker?
Docker Hierarchy
Image Container Service Stack
https://hub.docker.com
@danaluther
Basic Stack for PHP Apache on :8080
docker-compose.yml
https://docs.docker.com/compose/compose-
fi
le/
version: “3.7"


services:


php:


image: php:7.4-apache


ports:


- 8080
:
80


volumes:


- ./src:/var/
w
w
w
/html
@danaluther
version: “3.7"


services:


php:


image: php:7.4-apache


ports:


- 8080
:
80


volumes:


- ./src:/var/
w
w
w
/html


command:[


‘bash’, ‘
-
c’,


‘docker
-
php
-
ext
-
install
-
j$$(nproc) mysqli pdo_mysql
&
&
apache2-foreground’


]


db:


image: mysql


environment:


- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_pwd


secrets:


- db_pwd


secrets:


db_pwd:


file: ./root_db_password.txt
@danaluther
version: “3.7"


services:


php:


image: php:8.0-apache


ports:


- 8080
:
80


volumes:


- ./src:/var/
w
w
w
/html


command:[


‘bash’, ‘
-
c’,


‘docker
-
php
-
ext
-
install
-
j$$(nproc) mysqli pdo_mysql
&
&
apache2-foreground’


]


db:


image: mysql


environment:


- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_pwd


secrets:


- db_pwd


secrets:


db_pwd:


file: ./root_db_password.txt
@danaluther
version: “3.7"


services:


php:


image: php:8.1-rc—apache


ports:


- 8080
:
80


volumes:


- ./src:/var/
w
w
w
/html


command:[


‘bash’, ‘
-
c’,


‘docker
-
php
-
ext
-
install
-
j$$(nproc) mysqli pdo_mysql
&
&
apache2-foreground’


]


db:


image: mysql


environment:


- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_pwd


secrets:


- db_pwd


secrets:


db_pwd:


file: ./root_db_password.txt
@danaluther
Deploy the Stack on a Swarm
(Group of machines … or just one machine)
> docker stack deploy
-
c docker
-
compose-8.yml test
> docker swarm init
@danaluther
Voila!
http://localhost:8080
@danaluther
Voila!
http://localhost:8080
@danaluther
No swarm? No problem…
> docker
-
compose up
(Well, mostly no problem. No services list, secrets list, etc)
@danaluther
No swarm? No problem…
> docker
-
compose up
(Well, mostly no problem. No services list, secrets list, etc)
@danaluther
@danaluther
Creating a Docker Secret
The secret is in the stack…
…


db:


image: mysql


environment:


- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_pwd


secrets:


- db_pwd


secrets:


db_pwd:


file: ./root_db_password.txt
@danaluther
Creating a Docker Secret
The secret is in the stack…
…


db:


image: mysql


environment:


- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_pwd


secrets:


- db_pwd


secrets:


db_pwd:


file: ./root_db_password.txt
@danaluther
Check the containers…
docker container ls
@danaluther
Check the containers…
docker container ls
@danaluther
Inspect the container for the secret
docker container inspect
@danaluther
Inspect the container for the secret
docker container inspect
> docker container inspect $(docker ps
-
lq
-
f name=test_db)
> docker container inspect ff8dc39f919f
> docker container inspect test_db.1.l8enz0qx7x8zci4156gh7i0qy
@danaluther
Inspect the container for the secret
docker container inspect
> docker container inspect kiskis_db_1
> docker container inspect 378020331e87
> docker container inspect $(docker ps
-
lq
-
f name=test_db)
> docker container inspect ff8dc39f919f
> docker container inspect test_db.1.l8enz0qx7x8zci4156gh7i0qy
@danaluther
Inspect the container for the secret
docker container inspect
@danaluther
Inspect the container for the secret
docker container inspect
@danaluther
Inspect the container for the secret
docker container inspect
@danaluther
What's actually in the Secret?
@danaluther
What's actually in the Secret?
@danaluther
Can the container change the secret?
Nope!!
@danaluther
Can *I* change the secret?
Yes, yes I can.
@danaluther
Can *I* change the secret?
Yes, yes I can.
If I used docker stack deploy.
@danaluther
Updating a Docker Secret
(Ok, you can’t actually update it, you have to replace it.)
> docker secret create db_pwd.2 updatedcontent.txt
@danaluther
Updating a Docker Secret
(Ok, you can’t actually update it, you have to replace it.)
> docker service update
-
-
secret
-
rm test_db_pwd 


-
-
secret
-
add src=db_pwd.2,target=db_pwd test_db
@danaluther
Confirm the update
Updating the service launched a new container with a new secret.
New:
Original:
@danaluther
Great, but I don’t care about the database…
Right - lets put the secret to use in our DI container
@danaluther
Great, but I don’t care about the database…
Right - lets put the secret to use in our DI container
@danaluther
Sample API Object v3 with $_ENV via DI
Constructor moved to DI Container
require 'vendor/autoload.php';


use YiisoftDiContainer;


$container = new Container([


ExampleSampleObjectConstructed
:
:
class
=
>
[


	
'class'
=
>
ExampleSampleObjectConstructed
:
:
class,


	
'__construct()'
=
>
[$_ENV['MY_SECRET_KEY']]


],


]); $container
-
>
get(ExampleSampleObjectConstructed
:
:
class)
@danaluther
Sample API Object v3 with $_ENV via DI
Constructor moved to DI Container
require 'vendor/autoload.php';


use YiisoftDiContainer;


$container = new Container([


ExampleSampleObjectConstructed
:
:
class
=
>
[


	
'class'
=
>
ExampleSampleObjectConstructed
:
:
class,


	
'__construct()'
=
>
[$_ENV['MY_SECRET_KEY']]


],


]); $container
-
>
get(ExampleSampleObjectConstructed
:
:
class)
@danaluther
PHP stack with secrets
version: "3.7"


services:


php:


image: php:8.1-rc
-
apache


ports:


- 8081
:
80


volumes:


- ./src:/var/
w
w
w
/html


environment:


- MY_SECRET_KEY=SomeKeyValue


secrets:


- hiddenkey


- hiddenkey2


secrets:


hiddenkey:


file: ./secrets/secret
-
key
-
val.txt


hiddenkey2
:


file: ./secrets/secret
-
key
-
val2.txt
@danaluther
Deploy the Stack on a Swarm
(Don’t need to init, just re-deploy for updates)
> docker stack deploy
-
c docker
-
compose-8-1-nodb.yml test
@danaluther
Sample API Object v3 with secret via DI
Container populated from secret
require 'vendor/autoload.php';


use YiisoftDiContainer;


$container = new Container([


ExampleSampleObjectConstructed
:
:
class
=
>
[


	
'class'
=
>
ExampleSampleObjectConstructed
:
:
class,


	
'__construct()'
=
>
[file_get_contents('/run/secrets/hiddenkey')]


],


]);
@danaluther
Sample API Object v3 with secret via DI
Container populated from secret
require 'vendor/autoload.php';


use YiisoftDiContainer;


$container = new Container([


ExampleSampleObjectConstructed
:
:
class
=
>
[


	
'class'
=
>
ExampleSampleObjectConstructed
:
:
class,


	
'__construct()'
=
>
[file_get_contents('/run/secrets/hiddenkey')]


],


]); $container
-
>
get(ExampleSampleObjectConstructed
:
:
class)
@danaluther
Define multiple objects in the container
Multiple classes, multiple con
fi
gurations of one class
$container = new Container([


	
ExampleSampleObjectConstructed
:
:
class
=
>
[


	
	
'class'
=
>
ExampleSampleObjectConstructed
:
:
class,


	
	
'__construct()'
=
>
[file_get_contents('/run/secrets/hiddenkey')]


	
],


	
ExamplePartnerConfigIdentifier
:
:
OPT_CONFIG_1
=
>
[


	
	
'class'
=
>
ExampleSampleObjectConstructed
:
:
class,


	
	
'__construct()'
=
>
[file_get_contents('/run/secrets/hiddenkey2')]


	
],


	
ExamplePartnerConfigIdentifier
:
:
OPT_CONFIG_2
=
>
[


	
	
'class'
=
>
ExampleSampleObjectConstructed
:
:
class,


	
	
'__construct()'
=
>
['You can read me in the source repo.']


	
],


]);
@danaluther
Using constants to keep things tidy
(Yes, it wants to be an enum, but we’re 7.4 compatible currently)
class PartnerConfigIdentifier


{


	
public const DEFAULT_CONFIG = self
:
:
class.':default';


	
public const OPT_CONFIG_1 = self
:
:
class.':opt1';


	
public const OPT_CONFIG_2 = self
:
:
class.':opt2';


	
public const OPT_CONFIG_3 = self
:
:
class.':opt3';


}
@danaluther
Using constants to keep things tidy
(Yes, it wants to be an enum, but we’re 7.4 compatible currently)
class PartnerConfigIdentifier


{


	
public const DEFAULT_CONFIG = self
:
:
class.':default';


	
public const OPT_CONFIG_1 = self
:
:
class.':opt1';


	
public const OPT_CONFIG_2 = self
:
:
class.':opt2';


	
public const OPT_CONFIG_3 = self
:
:
class.':opt3';


}
@danaluther
Create multiple objects via the container
$container
-
>
get(ExampleSampleObjectConstructed
:
:
class);
$container
-
>
get(ExamplePartnerConfigIdentifier
:
:
OPT_CONFIG_1);
$container
-
>
get(ExamplePartnerConfigIdentifier
:
:
OPT_CONFIG_2);
@danaluther
Questions??
Ask now or tweet at me if you think of it later!
https://www.linkedin.com/in/danaluther
dluther@envisageinternational.com
https://joind.in/talk/78c5b
🤔
?
? ?
?
https://github.com/DanaLuther/kiskis
1 of 92

Recommended

WCLV13 JavaScriptWCLV13 JavaScript
WCLV13 JavaScriptJeffrey Zinn
1.8K views33 slides
Motion Django MeetupMotion Django Meetup
Motion Django MeetupMike Malone
7.4K views50 slides
Api DesignApi Design
Api Designsumithra jonnalagadda
593 views44 slides
深入淺出 MVC深入淺出 MVC
深入淺出 MVCJace Ju
20.8K views60 slides

More Related Content

Recently uploaded(20)

Is Entireweb better than GoogleIs Entireweb better than Google
Is Entireweb better than Google
sebastianthomasbejan10 views
Sustainable MarketingSustainable Marketing
Sustainable Marketing
Theo van der Zee7 views
WEB 2.O TOOLS: Empowering education.pptxWEB 2.O TOOLS: Empowering education.pptx
WEB 2.O TOOLS: Empowering education.pptx
narmadhamanohar218 views
Serverless cloud architecture patternsServerless cloud architecture patterns
Serverless cloud architecture patterns
Jimmy Dahlqvist17 views
google forms survey (1).pptxgoogle forms survey (1).pptx
google forms survey (1).pptx
MollyBrown8614 views
childcare.pdfchildcare.pdf
childcare.pdf
fatma alnaqbi13 views
Pen Testing - Allendevaux.pdfPen Testing - Allendevaux.pdf
Pen Testing - Allendevaux.pdf
SourabhKumar328076 views
informing ideas.docxinforming ideas.docx
informing ideas.docx
MollyBrown8612 views
UiPath Document Understanding_Day 2.pptxUiPath Document Understanding_Day 2.pptx
UiPath Document Understanding_Day 2.pptx
RohitRadhakrishnan8265 views
informationinformation
information
khelgishekhar6 views
Existing documentaries (1).docxExisting documentaries (1).docx
Existing documentaries (1).docx
MollyBrown8613 views
DU Series - Day 4.pptxDU Series - Day 4.pptx
DU Series - Day 4.pptx
UiPathCommunity77 views
 FS Design 2024 V2.pptx FS Design 2024 V2.pptx
FS Design 2024 V2.pptx
paswanlearning7 views
DU_SERIES_Session1.pdfDU_SERIES_Session1.pdf
DU_SERIES_Session1.pdf
RohitRadhakrishnan8807 views

Keep it Secret, Keep it Safe - Docker Secrets and DI

  • 1. @danaluther Keep it Secret, Keep it Safe Docker Secrets and DI (Containers) https://joind.in/talk/78c5b https://github.com/DanaLuther/kiskis
  • 2. @danaluther What are we keeping secret? All the things? (no… but de fi nitely the important things)
  • 3. @danaluther What are we keeping secret? All the things? (no… but de fi nitely the important things) • File Based Credentials
  • 4. @danaluther What are we keeping secret? All the things? (no… but de fi nitely the important things) • File Based Credentials • SSH key fi les
  • 5. @danaluther What are we keeping secret? All the things? (no… but de fi nitely the important things) • File Based Credentials • SSH key fi les • Json auth fi les
  • 6. @danaluther What are we keeping secret? All the things? (no… but de fi nitely the important things) • File Based Credentials • SSH key fi les • Json auth fi les • Variable Credentials
  • 7. @danaluther What are we keeping secret? All the things? (no… but de fi nitely the important things) • File Based Credentials • SSH key fi les • Json auth fi les • Variable Credentials • API keys and tokens
  • 8. @danaluther What are we keeping secret? All the things? (no… but de fi nitely the important things) • File Based Credentials • SSH key fi les • Json auth fi les • Variable Credentials • API keys and tokens • Any value that could compromise security / grant access to your data or accounts.
  • 9. @danaluther Isn't it already safe? …Ish. It depends - how are you storing it currently?
  • 10. @danaluther Isn't it already safe? …Ish. It depends - how are you storing it currently? • Storing credentials directly into a repo
  • 11. @danaluther Isn't it already safe? …Ish. It depends - how are you storing it currently? • Storing credentials directly into a repo • Readable by anyone with access to that repo
  • 12. @danaluther Isn't it already safe? …Ish. It depends - how are you storing it currently? • Storing credentials directly into a repo • Readable by anyone with access to that repo • Exposed in coverage reports or anything that includes the source code in analysis or reporting displays
  • 13. @danaluther Isn't it already safe? …Ish. It depends - how are you storing it currently? • Storing credentials directly into a repo • Readable by anyone with access to that repo • Exposed in coverage reports or anything that includes the source code in analysis or reporting displays • Storing credentials in ENV variables
  • 14. @danaluther Isn't it already safe? …Ish. It depends - how are you storing it currently? • Storing credentials directly into a repo • Readable by anyone with access to that repo • Exposed in coverage reports or anything that includes the source code in analysis or reporting displays • Storing credentials in ENV variables • Exposed via phpinfo, server dumps, or to anyone who has compromised the server
  • 15. @danaluther Isn't it already safe? …Ish. It depends - how are you storing it currently? • Storing credentials directly into a repo • Readable by anyone with access to that repo • Exposed in coverage reports or anything that includes the source code in analysis or reporting displays • Storing credentials in ENV variables • Exposed via phpinfo, server dumps, or to anyone who has compromised the server • Not static and has the potential to be modi fi ed nefariously
  • 16. @danaluther Does it really matter? I don’t know … does it?
  • 17. @danaluther Does it really matter? I don’t know … does it? • How important is the service or information being used?
  • 18. @danaluther Does it really matter? I don’t know … does it? • How important is the service or information being used? • How big is the impact if that service is accessed by another?
  • 19. @danaluther Does it really matter? I don’t know … does it? • How important is the service or information being used? • How big is the impact if that service is accessed by another? • Is the credential the sole key to access, or is does the service have additional factors in play?
  • 20. @danaluther Does it really matter? I don’t know … does it? • How important is the service or information being used? • How big is the impact if that service is accessed by another? • Is the credential the sole key to access, or is does the service have additional factors in play? • What is the risk level compared to the technical debt?
  • 21. @danaluther Does it really matter? I don’t know … does it? • How important is the service or information being used? • How big is the impact if that service is accessed by another? • Is the credential the sole key to access, or is does the service have additional factors in play? • What is the risk level compared to the technical debt? • Does the information get published into your application as part of the public UI?
  • 22. @danaluther Sample API Object Class with public API credential property class SampleObject { public string $myApiKey = 'ABC1234'; public function connect() { / / Do something with $myApiKey here } }
  • 23. @danaluther Sample API Object Class with public API credential property class SampleObject { public string $myApiKey = 'ABC1234'; public function connect() { / / Do something with $myApiKey here } } new ExampleSampleObject()
  • 24. @danaluther Sample API Object v2 Class with API credential property class SampleObjectMoreSecure { private string $myApiKey = 'ABC1234'; public function connect() { / / Do something with $myApiKey here } }
  • 25. @danaluther Sample API Object v2 Class with API credential property class SampleObjectMoreSecure { private string $myApiKey = 'ABC1234'; public function connect() { / / Do something with $myApiKey here } } new ExampleSampleObjectMoreSecure()
  • 26. @danaluther Sample API Object v3 Class with constructed private API credential property class SampleObjectConstructed { private string $_myApiKey; public function __construct(string $apiKey) { $this - > _myApiKey = $apiKey; } public function connect() { / / Do something } }
  • 27. @danaluther Sample API Object v3 Class with constructed private API credential property class SampleObjectConstructed { private string $_myApiKey; public function __construct(string $apiKey) { $this - > _myApiKey = $apiKey; } public function connect() { / / Do something } } new ExampleSampleObjectConstructed('Someothervalue')
  • 28. @danaluther Sample API Object v3 with $_ENV Class with constructed private API credential property class SampleObjectConstructed { private string $_myApiKey; public function __construct(string $apiKey) { $this - > _myApiKey = $apiKey; } public function connect() { / / Do something } }
  • 29. @danaluther Sample API Object v3 with $_ENV Class with constructed private API credential property class SampleObjectConstructed { private string $_myApiKey; public function __construct(string $apiKey) { $this - > _myApiKey = $apiKey; } public function connect() { / / Do something } } new ExampleSampleObjectConstructed($_ENV['MY_SECRET_KEY'])
  • 30. @danaluther Sample API Object v3 with $_ENV Class with constructed private API credential property class SampleObjectConstructed { private string $_myApiKey; public function __construct(string $apiKey) { $this - > _myApiKey = $apiKey; } public function connect() { / / Do something } } new ExampleSampleObjectConstructed($_ENV['MY_SECRET_KEY'])
  • 31. @danaluther Dependency Injection Containers So, what is it and how does it help us??
  • 32. @danaluther Dependency Injection Containers So, what is it and how does it help us?? • Does NOT help to solve the issue of fi le based credentials.
  • 33. @danaluther Dependency Injection Containers So, what is it and how does it help us?? • Does NOT help to solve the issue of fi le based credentials. • Does help to solve the issue of class based or variable credential strings.
  • 34. @danaluther Dependency Injection Containers So, what is it and how does it help us?? • Does NOT help to solve the issue of fi le based credentials. • Does help to solve the issue of class based or variable credential strings. • Creates a map that de fi nes the default properties to be assigned to an object when that object is created via the container.
  • 35. @danaluther Don’t reinvent the wheel. https://packagist.org
  • 36. @danaluther Add your DI package to composer composer.json { "require": { "yiisoft/di": "^3.0.x - dev", "yiisoft/injector": "^1.0", "yiisoft/definitions": "^3.0.x - dev" } }
  • 37. @danaluther Install the composer packages docker run --rm -v $PWD:/app composer update https://hub.docker.com/_/composer
  • 38. @danaluther Sample API Object v3 with $_ENV via DI Constructor moved to DI Container require 'vendor/autoload.php'; use YiisoftDiContainer; $container = new Container([ ExampleSampleObjectConstructed : : class = > [ 'class' = > ExampleSampleObjectConstructed : : class, '__construct()' = > [$_ENV['MY_SECRET_KEY']] ], ]);
  • 39. @danaluther Sample API Object v3 with $_ENV via DI Constructor moved to DI Container require 'vendor/autoload.php'; use YiisoftDiContainer; $container = new Container([ ExampleSampleObjectConstructed : : class = > [ 'class' = > ExampleSampleObjectConstructed : : class, '__construct()' = > [$_ENV['MY_SECRET_KEY']] ], ]);
  • 40. @danaluther Sample API Object v3 with $_ENV via DI Constructor moved to DI Container require 'vendor/autoload.php'; use YiisoftDiContainer; $container = new Container([ ExampleSampleObjectConstructed : : class = > [ 'class' = > ExampleSampleObjectConstructed : : class, '__construct()' = > [$_ENV['MY_SECRET_KEY']] ], ]); $container - > get(ExampleSampleObjectConstructed : : class)
  • 41. @danaluther But is it secret? Is it safe? Lets check those $_ENV vars …
  • 42. @danaluther But is it secret? Is it safe? Lets check those $_ENV vars …
  • 43. @danaluther Docker Secrets What are they and how do they help us?
  • 44. @danaluther Docker Secrets What are they and how do they help us? • Does help to solve the issue of fi le based credentials.
  • 45. @danaluther Docker Secrets What are they and how do they help us? • Does help to solve the issue of fi le based credentials. • Does help to solve the issue of class based or variable credential strings.
  • 46. @danaluther Docker Secrets What are they and how do they help us? • Does help to solve the issue of fi le based credentials. • Does help to solve the issue of class based or variable credential strings. • Created as elements of a Docker stack and written to read-only fi les in the container they are attached to.
  • 47. @danaluther Docker Secrets What are they and how do they help us? • Does help to solve the issue of fi le based credentials. • Does help to solve the issue of class based or variable credential strings. • Created as elements of a Docker stack and written to read-only fi les in the container they are attached to. • Can only be be modi fi ed by the stack when a new container is created.
  • 48. @danaluther Docker Secrets What are they and how do they help us? • Does help to solve the issue of fi le based credentials. • Does help to solve the issue of class based or variable credential strings. • Created as elements of a Docker stack and written to read-only fi les in the container they are attached to. • Can only be be modi fi ed by the stack when a new container is created. • Cannot be exposed through inspection via the stack or parent machine. Only visible in the container where it has been mounted.
  • 49. @danaluther What is Docker? (Jumped ahead there didn’t I…) https://www.docker.com
  • 50. @danaluther What is Docker? Docker Hierarchy https://hub.docker.com
  • 51. @danaluther What is Docker? Docker Hierarchy Image Container Service Stack https://hub.docker.com
  • 52. @danaluther Basic Stack for PHP Apache on :8080 docker-compose.yml https://docs.docker.com/compose/compose- fi le/ version: “3.7" services: php: image: php:7.4-apache ports: - 8080 : 80 volumes: - ./src:/var/ w w w /html
  • 53. @danaluther version: “3.7" services: php: image: php:7.4-apache ports: - 8080 : 80 volumes: - ./src:/var/ w w w /html command:[ ‘bash’, ‘ - c’, ‘docker - php - ext - install - j$$(nproc) mysqli pdo_mysql & & apache2-foreground’ ] db: image: mysql environment: - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_pwd secrets: - db_pwd secrets: db_pwd: file: ./root_db_password.txt
  • 54. @danaluther version: “3.7" services: php: image: php:8.0-apache ports: - 8080 : 80 volumes: - ./src:/var/ w w w /html command:[ ‘bash’, ‘ - c’, ‘docker - php - ext - install - j$$(nproc) mysqli pdo_mysql & & apache2-foreground’ ] db: image: mysql environment: - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_pwd secrets: - db_pwd secrets: db_pwd: file: ./root_db_password.txt
  • 55. @danaluther version: “3.7" services: php: image: php:8.1-rc—apache ports: - 8080 : 80 volumes: - ./src:/var/ w w w /html command:[ ‘bash’, ‘ - c’, ‘docker - php - ext - install - j$$(nproc) mysqli pdo_mysql & & apache2-foreground’ ] db: image: mysql environment: - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_pwd secrets: - db_pwd secrets: db_pwd: file: ./root_db_password.txt
  • 56. @danaluther Deploy the Stack on a Swarm (Group of machines … or just one machine) > docker stack deploy - c docker - compose-8.yml test > docker swarm init
  • 59. @danaluther No swarm? No problem… > docker - compose up (Well, mostly no problem. No services list, secrets list, etc)
  • 60. @danaluther No swarm? No problem… > docker - compose up (Well, mostly no problem. No services list, secrets list, etc)
  • 62. @danaluther Creating a Docker Secret The secret is in the stack… … db: image: mysql environment: - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_pwd secrets: - db_pwd secrets: db_pwd: file: ./root_db_password.txt
  • 63. @danaluther Creating a Docker Secret The secret is in the stack… … db: image: mysql environment: - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_pwd secrets: - db_pwd secrets: db_pwd: file: ./root_db_password.txt
  • 66. @danaluther Inspect the container for the secret docker container inspect
  • 67. @danaluther Inspect the container for the secret docker container inspect > docker container inspect $(docker ps - lq - f name=test_db) > docker container inspect ff8dc39f919f > docker container inspect test_db.1.l8enz0qx7x8zci4156gh7i0qy
  • 68. @danaluther Inspect the container for the secret docker container inspect > docker container inspect kiskis_db_1 > docker container inspect 378020331e87 > docker container inspect $(docker ps - lq - f name=test_db) > docker container inspect ff8dc39f919f > docker container inspect test_db.1.l8enz0qx7x8zci4156gh7i0qy
  • 69. @danaluther Inspect the container for the secret docker container inspect
  • 70. @danaluther Inspect the container for the secret docker container inspect
  • 71. @danaluther Inspect the container for the secret docker container inspect
  • 74. @danaluther Can the container change the secret? Nope!!
  • 75. @danaluther Can *I* change the secret? Yes, yes I can.
  • 76. @danaluther Can *I* change the secret? Yes, yes I can. If I used docker stack deploy.
  • 77. @danaluther Updating a Docker Secret (Ok, you can’t actually update it, you have to replace it.) > docker secret create db_pwd.2 updatedcontent.txt
  • 78. @danaluther Updating a Docker Secret (Ok, you can’t actually update it, you have to replace it.) > docker service update - - secret - rm test_db_pwd - - secret - add src=db_pwd.2,target=db_pwd test_db
  • 79. @danaluther Confirm the update Updating the service launched a new container with a new secret. New: Original:
  • 80. @danaluther Great, but I don’t care about the database… Right - lets put the secret to use in our DI container
  • 81. @danaluther Great, but I don’t care about the database… Right - lets put the secret to use in our DI container
  • 82. @danaluther Sample API Object v3 with $_ENV via DI Constructor moved to DI Container require 'vendor/autoload.php'; use YiisoftDiContainer; $container = new Container([ ExampleSampleObjectConstructed : : class = > [ 'class' = > ExampleSampleObjectConstructed : : class, '__construct()' = > [$_ENV['MY_SECRET_KEY']] ], ]); $container - > get(ExampleSampleObjectConstructed : : class)
  • 83. @danaluther Sample API Object v3 with $_ENV via DI Constructor moved to DI Container require 'vendor/autoload.php'; use YiisoftDiContainer; $container = new Container([ ExampleSampleObjectConstructed : : class = > [ 'class' = > ExampleSampleObjectConstructed : : class, '__construct()' = > [$_ENV['MY_SECRET_KEY']] ], ]); $container - > get(ExampleSampleObjectConstructed : : class)
  • 84. @danaluther PHP stack with secrets version: "3.7" services: php: image: php:8.1-rc - apache ports: - 8081 : 80 volumes: - ./src:/var/ w w w /html environment: - MY_SECRET_KEY=SomeKeyValue secrets: - hiddenkey - hiddenkey2 secrets: hiddenkey: file: ./secrets/secret - key - val.txt hiddenkey2 : file: ./secrets/secret - key - val2.txt
  • 85. @danaluther Deploy the Stack on a Swarm (Don’t need to init, just re-deploy for updates) > docker stack deploy - c docker - compose-8-1-nodb.yml test
  • 86. @danaluther Sample API Object v3 with secret via DI Container populated from secret require 'vendor/autoload.php'; use YiisoftDiContainer; $container = new Container([ ExampleSampleObjectConstructed : : class = > [ 'class' = > ExampleSampleObjectConstructed : : class, '__construct()' = > [file_get_contents('/run/secrets/hiddenkey')] ], ]);
  • 87. @danaluther Sample API Object v3 with secret via DI Container populated from secret require 'vendor/autoload.php'; use YiisoftDiContainer; $container = new Container([ ExampleSampleObjectConstructed : : class = > [ 'class' = > ExampleSampleObjectConstructed : : class, '__construct()' = > [file_get_contents('/run/secrets/hiddenkey')] ], ]); $container - > get(ExampleSampleObjectConstructed : : class)
  • 88. @danaluther Define multiple objects in the container Multiple classes, multiple con fi gurations of one class $container = new Container([ ExampleSampleObjectConstructed : : class = > [ 'class' = > ExampleSampleObjectConstructed : : class, '__construct()' = > [file_get_contents('/run/secrets/hiddenkey')] ], ExamplePartnerConfigIdentifier : : OPT_CONFIG_1 = > [ 'class' = > ExampleSampleObjectConstructed : : class, '__construct()' = > [file_get_contents('/run/secrets/hiddenkey2')] ], ExamplePartnerConfigIdentifier : : OPT_CONFIG_2 = > [ 'class' = > ExampleSampleObjectConstructed : : class, '__construct()' = > ['You can read me in the source repo.'] ], ]);
  • 89. @danaluther Using constants to keep things tidy (Yes, it wants to be an enum, but we’re 7.4 compatible currently) class PartnerConfigIdentifier { public const DEFAULT_CONFIG = self : : class.':default'; public const OPT_CONFIG_1 = self : : class.':opt1'; public const OPT_CONFIG_2 = self : : class.':opt2'; public const OPT_CONFIG_3 = self : : class.':opt3'; }
  • 90. @danaluther Using constants to keep things tidy (Yes, it wants to be an enum, but we’re 7.4 compatible currently) class PartnerConfigIdentifier { public const DEFAULT_CONFIG = self : : class.':default'; public const OPT_CONFIG_1 = self : : class.':opt1'; public const OPT_CONFIG_2 = self : : class.':opt2'; public const OPT_CONFIG_3 = self : : class.':opt3'; }
  • 91. @danaluther Create multiple objects via the container $container - > get(ExampleSampleObjectConstructed : : class); $container - > get(ExamplePartnerConfigIdentifier : : OPT_CONFIG_1); $container - > get(ExamplePartnerConfigIdentifier : : OPT_CONFIG_2);
  • 92. @danaluther Questions?? Ask now or tweet at me if you think of it later! https://www.linkedin.com/in/danaluther dluther@envisageinternational.com https://joind.in/talk/78c5b 🤔 ? ? ? ? https://github.com/DanaLuther/kiskis