Spring Tips: Easy Password Rotation with Hashicorp Vault

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi spring fans welcome to another installment of spring tips you know I really like security but I think it's very difficult to do well and so I try to cover it uh whenever I can knowing full well that it's best to stand on the shoulders of giants here right where I'm very happy to Riff to innovate Etc and lots of other domains I feel like security is one of those places for which I am just not nearly qualified enough and so whenever I can I like to employ tools and Frameworks and Technologies built by people purpose built by people who know what they're doing one of those tools that like is Hashi Corp Vault vault is a amazing way to deal with security passwords right credentials and to store them in a secure way and obviously there's it's like a database for credentials and there's a lot to it there's a lot to Hash Corb Vault I mean at the simplest way at the simplest level you could just think of it as like another key value store for secure values and in that respect I suppose you could just think of it as another kind of configuration server another configuration Source just like the springcloud config server or console or whatever um and yeah spring will let you treat it like that you can certainly inject keys and values from Vault and use them as part of the spring environment abstraction and through the at Value annotation and through configuration Pro property objects in Spring boot um but it it also has some other amazing features and it integrates with a lot of other pieces of key infrastructure in your organization including your database it can actually be used for example to rotate passwords for your database right this is very very cool because now you've reduced the window of opportunity for hackers who are trying to exploit your system you can even do things like if you're paying for the hashicorp vault sort of Premium offering you can even say I want to limit access to change these passwords to business hours for example right or or amazing things like that you can do Hardware encryption Hardware you know the the like the secure Enclave of your of your computer the extra secure Hardware right you can limit you can actually have things stored there and integrated with that I mean just an amazing piece of software there's a lot of really cool features uh and so if you're aware of how to configure deploy and administer Vault you can have everything your application your database your everything secured by Vault and it has plugins for lots of different things one of my favorite plugins is the one that works with databases right and there's even a whole backend a storage module in Vault designed to work with and to support rotating passwords for your different databases and of course I love postgres so I use postgres just about every everywhere I can it's not surprising at all that it supports postr as well so today friends we're going to look at Vault we're not going to look at vault as a configuration mechanism in fact we've already done that yeah you might recall way back in 2020 you remember 2020 nothing really happened that year famously we we looked at configuration I looked at the spring configuration approach right the ability to import configuration sources from Vault from springcloud config server from property files from the environment Etc so I'm not going to retread that particular water I don't feel like it's worth doing U we'll we'll kind of briefly see it in action here but it's only incidental instead what I wanted to talk about is reloadable configuration and how that integrates with spring Cloud Vault and the spring Cloud refresh scope this demo was driven by the efforts of Hashi Corp developer Advocate Rosemary Wong she's really really really brilliant and she's been you know I think I think she even we we did uh something together we she she and I worked on an an art arle some years ago and that article I think we talked about this as an opportunity and in that article we we used the refresh event the actuator refresh event to tell spring to reload its configuration and and there was some integration there with hash cor vault as an external thing that would then trigger a HTTP request to that endpoint and so the the the effect was the same you have the actuator the actuator in turn tells spring cloud and spring boot to reload its configuration and and everything therein would refresh itself including the configuration that was being drived from or sourced from hash cor vault which is good but it was sort of I mean something it it was sort of like the the password would would get rotated in Vault and then Vault would have to tell spring boot to update itself as opposed to Spring boot sort of just knowing to update itself right it' be I think it's better if the spring the spring application can pull the configuration it can re it can proactively refresh its own configuration as opposed to having to be being told to do so and so Rosemary she kept at it she I think she's been working on this you know intermittently or thinking about it and I think so last week she approached me and said I I think I've gotten a different way to do this and we we worked on it a little bit and um yeah this is what we're going to talk about today is what she came up with 99% of it was hers there I I little tiny not through the uh through the eye of a of a needle you could you could you could fit my contribution but but still still really really really cool demo so thank you Rosemary thank you hash for such an amazing piece of technology so you might be asking what is hashicorp Vault what does it do why would I use it well obviously there is nobody better to to answer these questions than rosem mayor herself so I'm going to hand it over to to Rosemary she'll give us a a quick debrief on the big picture of Vault what what it is how it is used and and so on and then we'll get right into it in a minute I'm Ros Wong and I'm a developer Advocate at Hashi Corp I work with a tool called hash vault which is a Secrets manager that manages the life cycle of Secrets basically anything that allows you to gain access to another system these can be certificates usernames and passwords or API tokens vault is very unique people like to use it for two main reasons the first is that it helps you consolidate your secrets in one place and determine who is going to be using those Secrets uh control how they're being revoked how they're being created created if you have a lot of secrets in a very large environment it's very hard to determine how they're being used and which systems are storing them so if you're storing them in one place like vault is very helpful for auditing who's accessing Vault to get access to the secret itself and therefore using the secret so it's particularly helpful if you want to verify whether or not secrets are being rotated on a certain Cadence or whether or not some old Secrets might be compromised the second reason people like to use vault is that vault has certain plugins called Secrets engines that automatically revoke and create secrets for you so if you don't want to manually store the secret in Vault and rotate it yourself you can ask Vault to handle that Cadence for you it will basically issue a lease for a secret until a certain time period is expired after that expiration it will remove those credentials revoke them from the target systems that it's trying to configure and some anybody who tries to use the old secret isn't going to be able to use it anymore so it's particularly helpful in improving this overall security of your applications and other services that might be accessing other systems all right let's dive right into it going to go to start. spring. AO I'm going to build a new app use Maven you know I'll call this a vault right we're going use Java 21 and later and then you know we can add the Vault configuration support here and we'll add the web support you can add the actuator support and very importantly we want the spring Cloud config support right we actually want the spring Cloud Core support it doesn't even need to be spring Cloud config so Cloud bootstrap be enough okay all right let's hit enter and open this up in our ID now first things first remember let's just let's just connect to Vault here okay so first things first how do we connect to Vault where do we get vault what is Vault Etc and so to that end I'm going to use a Docker compos file here okay copy desktop compose Doo okay and this dark compos file has post GES right it's got a database password payments a sorry a database called payments a password called post admin password and a user called and we're exposing it on Port 5432 and very importantly here we have Vault right 1.16.1 we're telling it to run Vault server ddev listen on these addresses so this is not a production deployment talk to your security people I'm sure they've got a real production environment you should be aware of that uses Vault and we're going to specify a vault Dev root token ID okay so we need to remember secret okay ports 8200 and 8200 we're going to run this here CD Vault okay so that's up and running now one need to initialize it so I've got this script here that does most of that work so let's start with this simple stuff here we're going to put a simple key and value in there in the database called Vault demo and the the key will be DB password and the value will be tiger so let's do that okay all right so we've added that now we want to configure our spring boot application to connect to and then work with that configuration So in theory we should be able to create a beam here okay read from Vault demo right and just let's just make sure we have you know this is Hello World kind of stuff but let's make sure that's working okay got a password PW all right good stuff so there's this so now I want to you know if I want if I want to run this application I need to authenticate I need to connect and I need to integrate so let's add some dependencies to our build here we've already got spring Cloud starter Vault config I'm going to add one more here called Vault config big uh database okay so copy and paste this and this will be the extra support for password rotations for databases okay so springcloud Vault config D databases we're going to add that to the class path I have a token and an address as environment variables in my shell so if I go here Echo Vault address that's pointing to the local Vault server and I have a token secret and you can remember we specified this token back here Vault Dev root token this is just for development this is not how it really works normally you'd have to unseal it using five different passwords and all that kind of stuff but uh okay for our development that's there so this is in the environment this is in the environment variable space for this Java program okay so when I run it that's being taken into account okay so we've got this now we also need to tell spring Cloud how to integrate with it first of all we want to import the configuration here I can say spring config import Vault colon SL springcloud needs to know about those tokens right that token in the URI so I'll say springcloud Vault U is Vault address right and the token is Vault token and of course I'm talking to a SQL database but it doesn't know about which one so let's go check our composed. yaml file and you can see we've got payments post admin password and post okay so let's specify those here I'll just copy and paste all that for reference spring data source post uh database password equals password so we're going to use this remember these are the seed usernames and passwords right the the very first connection and then username will be post GES and then the database the URL of course is jdbc colen postgresql Local Host payments all right so there we go so we don't need these anymore okay so now we should have what we need to be able to connect and get we should be able to connect to our SQL database and to get our one value out of the database and print it out let's try that out and see what happens okay DB password DB password okay so I think we're ready to go let's just check our configuration again everything looks oh hey hey hey hey uh actually this needs to line up with the database that we used earlier when we wrote that config right so do you remember we did Vault KV put secret vault demo right and then the DB password tiger so I can change it I can do vault which lines up with this right if I do that that'll be okay or I can do Vault demo in which case this needs to change right for my little simple example here so I'm going to change this well actually you know what let's just do that we'll re store the value there and then I'll restore this to just Vault okay so now let's run the program and see what we get okay there we go got a password Tiger but now if I go back here to just Vault demo now we got it in both databases let's change the demo name to Vault demu because I am a cow apparently and we restart this and that doesn't work right so you can see these things are intrinsically tied to each other so I'm I'm going to just restore it to Vault because why not that's what the uh project that we generated is called and it works out but just bear in mind there is a relationship there okay okay so this is just basic key value like get a value from the from the database but what we want to support is reloadable configuration okay and here we need to enable the database module for Vault okay okay so so I'll go back to my command line and I'll paste the following commands Okay let's see what those are so the first one is enable the database okay and there's a path here for the storage but it could be whatever and we're going to enable this right here this plugin and then we're going to use we're going to set up a plugin called post database plugin providing a connection URL uh specifying post username password the the schema the port and the database right I'm sorry this is the uh host name and uh we're going to write to database config payments payments is the name of our database it's what the application will do Etc so the allowed roles are a payments app username is postgres and the password is postgres admin password the same is we're using so I'm going to paste the following commands Okay and what that's done is it's enabled the database plugin and I've written the using the post database plugin I've written the I'm activating the configuration for that specifying the connection URL to the postgres payments database that we're creating here the allowed roles is the payments app the username is postgres and the password is postgres admin password again same as we have here right payment postc payment postc admin password and then we're saying we want to write a to the roles right not just config but the roles in the database we're providing a creation statement we're saying create Ro templated URL there with login password templated password until and then there's an expiration date there and then Grant all privileg on payments to this name and then specify a time delive now these are nonsensically uh short trivial values here just for our demo normally you'd have something like once a day or once a week or whatever you know the point is you want it you don't want your D because even the best password rotation is going to imply some momentary uh disruption to service right so you want to minimize it but also find a value that is safe so maybe you do it once a day or once a week or whatever it's up to you I'm sure your security people have notes so now we want to configure the database plug-in which again remember we have that support on the build spring Cloud spring Cloud Vault config databases so let's go here and what we're doing is we're saying spring Cloud Vault database enabled equals true okay good the role is the payments app we specified that in the command line just a second ago and the back end is the database plugin okay so we are on the same page there we also want to specify the life cycle for checking on leases and so on so that's what this is right here we're again super trivial very brief timeouts just for our demo okay okay so now we've got all the infrastructure in place let's let's go ahead and write some code finally finally finally okay so in order in order to write some code representing some payments we need to actually have a database called payments so I'm going to create a schema file here just paste all this in so I'm saying set the time zone as UTC create the extension if it doesn't exist for PG crypto create the table called payments specifying an ID a name a billing address and a created at table column and then we're going to delete from the payments and then insert a new value into the payments database okay with that I want to have a controller that returns payment information and uh you know we can just do at Bean router function server response you know HTTP end point okay so payments good server response. body and then what are the payments well let's just do a very simple jdbc query oh I don't have the uh did I specify the SQL database support in Spring when I created the project I don't think I did okay so we need jdbc command shift I to reimport and then we'll just inject the jdbc client here okay SQL select all from payments do query new row mapper and then we need a payment object of course so record payment and we've got these columns here we go string ID string name String build address and a an instant created at okay so there's that no problem okay add this list and then return that you could actually do a new Bean property R mapper and then just pass in the map to class payments. class and voila payment okay let's try that and then that and then that okay so we've got now our simple h be end point let's make sure that this is working I have to specify a SQL database driver as well so go back here post G copy and paste that go back to the build paste it in here command shift I and then reload and now what now it's complaining that I haven't initialized the database okay that makes sense so SQL in it always and it's not seeing the SQL database I wonder why it's complaining that I'm ah we have a we have ourselves a chicken and egg problem I need to able I need to run this schema here so that the plugin doesn't fail when I try and connect to to it on application startup that's kind of interesting okay no big deal but now let's restart let's just make sure I didn't screw anything up do I have everything in the right place post G oh wait no that's not going to work okay try this again here we go all right so now it's started I've made sure to initialize the SQL database I've got the right schema it's initialized my table so now if I go here and click on this I've got a table here on the left on the right rather go to tables open this okay so I've got my one record now what if I go to the HTP endpoint that we just created Local Host payments right what happened now well oh it's saying there's no no argument Constructor so I should have used a different uh let's see is it a record R mapper okay so it's saying that so I I tried it with the bean property role mapper that didn't work I have to change it to a data cost role mapper sorry the other one's what we would use for a Java Java Bean compatible thing but I'm using a record this is what you use instead as you can see this is new in 5.3 it works with data classes in cotlin uh and of course Java records Etc okay written by yurgen holler himself all right good so we've got now our simple HT point we're connected we're not secure but we are connected so this is good I'm going to make a request let me go to the browser and make a simple request here and you can see the problem that when I make the request I'm locked out right it says permission denied for table payments right so this is the Crux of the issue how do we update our data source which is being autoconfigured for us here to reflect this new world well we need to first of all take control of how the data source itself gets created so let's do that this way I'm going to create a bean of type data source and therefore these properties you know I'm going to still inject them you can see that they're being injected into the data source properties object spring. datas source. blah um and then I'm using that to then create the data source proper you know using the URL the username and the password and I'm logging out don't do this in your code but I'm logging out for our demo the username the password and the URL this is half of the problem but it's not it's not all of it right we still need to update our Bean once we've been rot once the password has been rotated and we can do that by specifying at refresh scope and this will make this Bean it'll make this Bean it'll recreate this Bean whenever a refresh event is published so we're close right this is the hard part now assuming that we have a ref ref fresh event this will trigger the recreation of The Bean which will then be you know it's what the jdpc client has is a proxy that wraps the actual underlying thing so the proxy is still valid it's just going to forward its invocations to an underlying Bean of type data source which is going to be recreated a sit in situ sort of whenever there's a refresh event which gets us to the hard part how and when do we get the refresh event and here friends we need to here friends we need to write a little let's take a look at the genius behind Rosemary's code the most important part which is the listener so when the application starts up we have a configuration class we've got a pointer to the context refresher this is part of spring Cloud context and we've got an application event publisher uh and when the application starts up we inject the database rooll and the back end that's specified in our properties right here roll backend Etc and we are adding a lease listener to our lease container which is part of the spring Cloud Vault project we're going to use a secret lease container which and we're going to add a lease listener so now we're checking okay if the event that's being published is for this particular path which is our database role or back end ourry backend and then our database rule you know backend for creds for/ database rule if that is the path of the the source of the event then we check and see if it's a secret leas expired event and if it is then we publish a refresh event this is in turn going to activate all it'll be it'll activate the recreation of all the beans that are annotated with at refresh scope so this Bean will get recreated uh when that event happens okay so this is the important part I forgot to specify the KV refresh interval so I'll go to my properties add this down here this is just a custom property that we're using for own edification restart okay so we're up and running you can see that now our data source is being used to create the the username and the password so now the URL is this the username is this where did we get that from well that's from Vault vault is giving us spring. datas source. username and spring. datas source. password overwriting whatever was in the property file here and of course this is you know random it looks V token payments blah blah blah something something something and so if we go to our endpoint now refresh there's the data but we have to now wait for a little while to see that the the value has changed it's going to get automatically rotated so I'm just going to let this do it thing will monitor the output here and while we're waiting before we start bear in mind there's also scheduling on this right so this code is actually pretty useful it does it automatically refreshes when there's a lease event here but also if you have a static value like that DB password that we had earlier and you change that well this will refresh whenever it sees that change as well that's what this interval was for is to periodically pull every whatever it was we had in that property file and then change you know publish an event and we could do the same thing here actually we could publish this we could put this in here as well we don't need the context refresher okay we'll go ahead and [Music] wait okay you can see that behind the scenes we have a refresh event listener right and it's recreated the context basically you know recreated the context with the new credential and so now if I want to make a call you can see the environment properties have been changed right so that's fine but we don't actually have the bean just yet because nobody's using the bean the the creation of The Bean Is lazy in this respect so let's go back to our endpoint make another request go back to our code and you can see jdbc V token payments blah blah blah this is new this is different from what it was back here right so it's 9s sorry qs9 leq and then go down here it's EG blah blah blah you see so the password was rotated we got updated immediately and as soon as we tried to then use that data source it recreated the bean because it realized it was invalid and and so on so in this way we have refreshable configuration and by the way we also have this there's nothing nothing has changed DB password has not changed uh but you know you can imagine what would happen if it had so with this we now have an application that is using the springcloud refresh event to you know correctly and usefully uh recreate data sources whenever the backend is changed this is a a really nice cooperation between the the database plugin for hasher Vault The springcloud Vault project the spring Cloud Vault database support as well uh and of course Spring Cloud's refresh scope and the refresh event infrastructure in Spring Cloud all these things come together to allow you to build applications that basically work as before it's not like my my payments controller is any different right I did nothing to this this is just a simple HT endpoint I'm using jdbc I make the request Etc but behind the scenes because I'm using dependenc in and because I have this nice sort of layered approach to building applications I'm able to seamlessly swap out a data source out from underneath the jdpc client without anything being the wiser this is a really good result for everybody it's also more secure so it's the more secure option while also remaining just as easy I hope you got something out of this my friends a big huge special thanks to my friend and teacher Rosemary over at hatch Corp again for this amazing initiative and effort and work uh and thanks to you all as always for watching I hope you got something out of it and we'll see you next time
Info
Channel: SpringDeveloper
Views: 2,765
Rating: undefined out of 5
Keywords: Web Development (Interest), spring, pivotal, Web Application (Industry) Web Application Framework (Software Genre), Java (Programming Language), Spring Framework, Software Developer (Project Role), Java (Software), Weblogic, IBM WebSphere Application Server (Software), IBM WebSphere (Software), WildFly (Software), JBoss (Venture Funded Company), cloud foundry, spring boot, spring cloud
Id: jWfyRrCUBMY
Channel Id: undefined
Length: 26min 32sec (1592 seconds)
Published: Tue May 14 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.