Files
cmc/README.md

513 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# art-get-arrays-jwt-springsecurity-angular
JSON Web Token (JWT) with Spring Security And Angular - Tutorial from Get Arrays (Udemy)
### Notes
#### Section 19: HTML Template
##### 134. Configuring routes
- Generate AppRoutingModule
- `ng generate module app-routing --flat --module=app`
- Modify `app-routing.module.ts`
#### Section 29: Security Management - Front End
##### 199. Unsubscribe using Subsink library
1. Install [SubSink](https://www.npmjs.com/package/subsink)
- `npm install subsink --save`
2. Use it
#### Section 30: Deployment
##### 202. Creating EC2 instance
Create EC2 instance with custom security rules
- open port 80, 5000, 443(ssh) for everyone
##### 203. Configure EC2 instance
1. Install apache web server
- `sudo service httpd start` -> service not found
- `sudo yum -y install httpd` -> OK
- `sudo service httpd status` -> running
- Go to EC2 public URL -> Apache Server Default Page
2. Test work
- Navigate to server content
- `cd /var/www/html`
- create sample html file
- `sudo nano index.html`
- `<h1>Welcome to AWS Apache server</h1>`
- Ctrl+O
- Ctrl+X
- Go to EC2 public URL -> Our web page
3. Install Java
- `sudo amazon-linux-extras install java-openjdk11`
4. Install MySQL
- `sudo wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm`
- `sudo wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm`
- `sudo yum localinstall mysql57-community-release-el7-11.noarch.rpm`
- `sudo yum install mysql-community-server`
5. Start MySQL
- `sudo systemctl start mysqld.service`
- `sudo systemctl status mysqld.service`
- Check for temporarily root password
- `sudo grep 'temporary password' /var/log/mysqld.log`
- `A temporary password is generated for root@localhost: idy7c#>jEetF`
- `sudo mysql_secure_installation`
- new password: `Supp0rtP0rta!`
- No for other questions
6. Configure mysql
- `sudo mysql -u root -p` -> enter password
- `show databases;`
- `create database support_portal;`
- `create user 'support_portal_user'@'localhost' identified by 'Supp0rt_Porta!_P@ssword';`
- `grant all privileges on support_portal.* to 'support_portal_user'@'localhost'; `
##### 206. Running in AWS
1. Copy JAR file to EC2 home folder (secured copy)
- `scp -i "certified-dev-assoc-course.pem" "C:\Users\Admin\IdeaProjects\Study\GetArrays\art-get-arrays-jwt-springsecurity-angular\support-portal-backend\target\support-portal.jar" ec2-user@ec2-13-51-129-89.eu-north-1.compute.amazonaws.com:~/`
2. Set Environment Variables
- `export PORTAL_MAIL_USERNAME="{{your_gmail_username}}"`
- `export PORTAL_MAIL_PASSWORD="{{your_gmail_password}}"`
- `export SPRING_PROFILES_ACTIVE="aws-local"`
3. Start java app
- `java -jar support-portal.jar`
4. Run as executable
- `sudo chmod 755 support-portal.jar`
- `ls -lh support-portal.jar` -> view permissions
- `./support-portal.jar`
##### 207. Deploying Angular Application
1. Build Angular Application
- `ng build --prod`
2. Upload dist/support-portal-frontend folder to EC2
- `scp -r -i "certified-dev-assoc-course.pem" "C:\Users\Admin\IdeaProjects\Study\GetArrays\art-get-arrays-jwt-springsecurity-angular\support-portal-frontend\dist\*" ec2-user@ec2-13-51-129-89.eu-north-1.compute.amazonaws.com:~/`
3. Move files to httpd directory
- `sudo cp ~/support-portal-frontend/* /var/www/html`
##### 208. Creating Unix Service
1. Create dedicated user to run this app as a service
- without ability to login
- `sudo adduser --home /var/lib/supporthome --shell /sbin/nologin supportuser`
- `sudo cat /etc/passwrd`
2. Add access for the system processes to access home folder's content
- `cd /var/lib`
- `ls -lh` -> only supportuser has access
- `sudo chmod 755 /var/lib/supporthome`
- owner has full access 7 (rwx) - read write execute
- others - 5 (r-x) - read and execute
3. Copy jar into supportuser home
- `cd ~`
- `sudo cp support-portal.jar /var/lib/supporthome`
4. Change ownership of jar file
- `ls -lh` -> owner is root
- `sudo chown supportuser:supportuser support-portal.jar`
- `ls -lh` -> owner is supportuser
5. Change permission to read and execute only for supportuser
- `sudo chmod 500 support-portal.jar`
6. Protect the file from accident deletion
- `sudo chattr +i support-portal.jar` - change attribute `+i` (add immutable)
- `rm support-portal.jar` ->
- ` cannot remove support-portal.jar: Operation not permitted`
- `sudo rm -f support-portal.jar` ->
- ` cannot remove support-portal.jar: Operation not permitted`
- (for deletion we need first remove immutability - `sudo chattr -i support-portal.jar`)
7. Create symbolic link
- `sudo ln -s /var/lib/supporthome/support-portal.jar /etc/init.d/supportapi`
- `ln` - link
- `-s` - symbolic
- `/etc/init.d` - init directory
- `supportapi` - name of service
- `cd /etc/init.d`
- `ls` -> we have supportapi
8. Start service
- `sudo service supportapi start`
- `sudo service supportapi status`
9. View logs
- `cd /var/log` -> `ls`
- `cat /var/log/supportapi.log`
- **or**
- `sudo vim supportapi.log` -> :qa for quit
- **or**
- `sudo tail -f /var/log/supportapi.log`
10. Setting Permanent Global Environment Variables for All Users
- `sudo nano /etc/environment`
- `SPRING_PROFILES_ACTIVE=aws-local`
##### 208.2 Creating Unix Service - Correct Way
- cd /etc/systemd/system
- Create a file named your-service.service and include the following:
```shell script
[Unit]
Description=Support Portal API
[Service]
User=supportuser
WorkingDirectory=/var/lib/supporthome
ExecStart=/var/lib/supporthome/support-portal.jar
Restart=always
Environment="SPRING_PROFILES_ACTIVE=aws-local"
[Install]
WantedBy=multi-user.target
```
- Reload the service files to include the new service.
- `sudo systemctl daemon-reload`
- Start your service
- `sudo systemctl start supportapi.service`
- To check the status of your service
- `sudo systemctl status supportapi.service`
- To enable your service on every reboot
- `sudo systemctl enable supportapi.service`
##### 209. Testing in Production
- Test with:
- Username: `art.shyshkin`
- Password: `17aH!?o>CJ`
- and another
- Username: `shyshkin.art`
- Password: `5C<"0dVx=>`
##### 33 deploy frontend into s3 bucket
1. S3 console
- Create bucket: `portal.shyshkin.net`
2. Build Angular app
- create `environment.test.ts`
- modify `angular.json`
- `ng build -c test`
3. Copy files from `dist/support-portal-frontend` to the bucket
4. Static website hosting
- Enable
- index.html
5. Allow public access
- `Block public access (bucket settings)` - All OFF
6. Edit bucket policy
- `{`
- ` "Version": "2012-10-17",`
- ` "Statement": [`
- ` {`
- ` "Sid": "PublicRead",`
- ` "Effect": "Allow",`
- ` "Principal": "*",`
- ` "Action": [`
- ` "s3:GetObject",`
- ` "s3:GetObjectVersion"`
- ` ],`
- ` "Resource": "arn:aws:s3:::portal.shyshkin.net/*"`
- ` }`
- ` ]`
- `}`
7. Visit `http://portal.shyshkin.net.s3-website.eu-north-1.amazonaws.com`
8. Make an Alias to Website
- Route 53 console
- Hosted zone: shyshkin.net
- Add record
- Name: portal
- Record Type: A
- Routing policy: Simple routing
- Alias: true
- Alias to S3 website endpoint
- Stockholm
- s3-website.eu-north-1.amazonaws.com
9. Tune CORS for backend
- add `http://portal.shyshkin.net`
##### 35.1 deploy MySQL into AWS RDS - with public access
1. RDS Console
- MySQL 8.0.23
- Dev/Test
- DB instance identifier: `portal-db`
- Master username: portal_user
- Master password: Supp0rt_Porta!_PAssword
- DB Instance: db.t3.micro
- Public access: yes
2. Additional configuration
- Initial database name: support_portal
3. Create DB
4. Create Security Group MySQLFromEverywheere
- allow port 3306 from everywhere (for testing purposes)
5. Attach SG MySQLFromEverywheere to DB instance
##### 35.2 deploy MySQL into AWS RDS - WITHOUT public access
1. Detach SG MySQLFromEverywheere
2. To access DB from EC2 `support-portal`
- attach `default` SG to EC2 (DB has `default` SG too)
3. Delete SG MySQLFromEverywheere
4. Run backend app with new profile (for testing)
- `java -jar -Dspring.profiles.active=aws-rds`
5. Change environment variable (for service)
- `sudo systemctl edit supportapi`
- Content:
- `[Service]`
- `Environment="SPRING_PROFILES_ACTIVE=aws-rds"`
##### 34.1 Create EC2 instance for Docker
- Create EC2 instance
- User Data:
```shell script
#!/bin/bash
yum update -y
amazon-linux-extras install -y docker
service docker start
usermod -a -G docker ec2-user
chkconfig docker on
mkdir -p /etc/systemd/system/docker.service.d
echo "[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H unix:// -H tcp://0.0.0.0:2375" > /etc/systemd/system/docker.service.d/options.conf
systemctl daemon-reload
systemctl restart docker
```
- Security group: `docker-security-group`
- Allow 8080 (tomcat), 2375 (from my PC), 22 (SSH)
- Allocate Elastic IP: `docker-elastic-ip`
- Associate `docker-elastic-ip` with `docker-ec2`
- In Route 53 create record `dockerapp` with `docker-ec2` public IP
#### 34.2 Allow Docker EC2 to Access RDS
- Create `mysql-vpc-security-group`
- Allow port 3306 from `docker-security-group`
- Attach SG to database in RDS `portal-db`
##### 34.3 Build and Run Docker image in Docker EC2
- `mvn clean package docker:build docker:start`
##### 34.4 Configure frontend to call new backend
- `ng build`
- upload `dist/support-portal-frontend` to S3
##### 34.5 Logging remote docker
- `mvn docker:logs`
- `mvn docker:logs -Ddocker.follow`
##### 34.6 Persisting images to EC2 filesystem
1. Initial state
- `docker container exec -it b36 bash`
- `pwd` -> /application
- `cd ~` -> `pwd` -> /root
- `ls` -> supportportal
- `ls supportportal/user` -> folders of users like `{UUID}`
2. State after rebooting EC2 instance
- same docker container
- `docker container exec -it b36 bash`
- `ls /root/supportportal/user` -> all left the same
3. State after recreating container (or new image)
- `mvn docker:stop docker:start`
- other container
- `docker container exec -it bc7 bash`
- **or**
- `docker container exec -it angular-support-portal-backend bash`
- `ls /root/supportportal/user` -> **No such file or directory**
4. Adding volume to store images between rebuilds
- add `<volume>/root/supportportal</volume>` - not successful
- add `<volume>~/supportportal:/root/supportportal</volume>` - Error
- `'~/supportportal' cannot be relativized, cannot resolve arbitrary user home paths.`
- add `<volume>/home/ec2-user/supportportal:/root/supportportal</volume>` - success
##### 36.1 Deploy Spring Boot JAR file on AWS Elastic Beanstalk
1. Info about deployment Spring Boot app on AWS
- AWS EBS expects for your apps to listen on port 5000
- Update your Spring Boot application.properties to use: server.port=5000
- Select Web App > Platform Java
- Upload the JAR file
2. Modify RDS security
- create SG `mysql-marker-sg` with no inbound riles
- modify SG `mysql-vpc-security-group` to allow 3306 from `mysql-marker-sg`
3. Deploy Spring Boot App to AWS
- Log into to AWS
- Navigate to Elastic Beanstalk
- Create a new application
- Select app type: Web Application
- Give it the name: `support-portal-backend`
- Create a new environment
- For platform, select: Java
- Select option to Upload your JAR file.
- Note: the screen says only WAR and ZIP files, but it does in fact accept JAR files
- Upload your JAR file: target/support-portal.jar (directly or though S3)
- I choose `https://art-sources.s3.eu-north-1.amazonaws.com/support-portal.jar`
- Configure More Options
- Single instance
- Instances
- EC2 Security Groups: `mysql-marker-sg`
- Software -> Environment properties
- SPRING_PROFILES_ACTIVE: aws-rds
- SERVER_PORT: 5000 (not necessary because we set it in application.yml)
- Create the application
4. View logs
- Supportportalbackend-env -> Logs -> Last 100 Lines
5. Once the app is created, then visit the app URL.
- Go to environment
- `http://supportportalbackend-env.eba-wfr5wya3.eu-north-1.elasticbeanstalk.com/`
- `{"timestamp":"2021-09-27T06:49:46.181755","httpStatusCode":403,"httpStatus":"FORBIDDEN","reason":"FORBIDDEN","message":"You need to log in to access this page"}`
- OK - it is working
6. Test work with frontend
- modify `environment.ts`
- `ng serve`
- `localhost:4200` -> OK
7. Create subdomain for beanstalk environment
- Route 53 console
- Create new Record for hosted zone `shyshkin.net`
- Record name: `portal-bean`
- Record type A
- Route traffic to `Alias to Elastic Beanstalk`
- `Supportportalbackend-env.eba-wfr5wya3.eu-north-1.elasticbeanstalk.com`
- Visit `http://portal-bean.shyshkin.net` -> have a response from spring boot app -> OK
- Test with Angular App: `localhost:4200`
##### 36.2 Providing HTTPS access to the backend through Elastic LoadBalancer (ELB) and Amazon Certificate Manager (ACM)
1. Provision certificate
- ACM console
- Provision certificates
- Request a public certificate
- Domain name: `portal-back-secure.shyshkin.net`
- DNS validation
- Create record in Route53
- About 30 minutes -> Pending validation (it took about a minute for me)
- Certificate issued
2. Create environment
- Beanstalk console
- Application -> `support-portal-backend`
- Create environment -> Web server environment -> Supportportalbackend-secured
- Domain -> Leave blank
- Java
- Application code -> Existing version
- Configure more options
- High Availability (with Load Balancer)
- Software -> Environment properties
- SPRING_PROFILES_ACTIVE: aws-rds
- Instances
- EC2 Security Groups: `mysql-marker-sg`
- Load Balancer -> Edit
- Listeners -> Add Listener
- Port: 443
- Protocol: HTTPS
- Certificate: `portal-back-secure.shyshkin.net - e0c...`
- SSL policy: ELBSecurityPolicy-TLS-1-2-Ext-2018-06 (how strong security policy will be)
- Add
- We may disable HTTP (80), but just keep it for now
- Save
- This is `custom configuration`
- Create environment
3. Create CNAME for load balancer URL
- Route53 console
- Hosted zone -> shyshkin.net
- Add Record
- Simple routing
- Record name: `portal-back-secure`.shyshkin.net
- Record type: CNAME
- Value: `supportportalbackend-secured.eba-wfr5wya3.eu-north-1.elasticbeanstalk.com`
4. Wait some time
5. Visit HTTP and HTTPS
- `http://portal-back-secure.shyshkin.net/` -> OK
- `https://portal-back-secure.shyshkin.net/` -> OK
6. View certificate info
- Chrome -> Lock sign
- Certificate
- Publisher
- CN = Amazon
- OU = Server CA 1B
- O = Amazon
- C = US
7. Verify Certificate in use
- ACM console - certificate for `portal-back-secure.shyshkin.net`
- In Use -> Yes
- Associated resources:
- `arn:aws:elasticloadbalancing:eu-north-1:392971033516:loadbalancer/app/awseb-AWSEB-1OGG0G42RZOR2/f2dec1e6adf1a4de`
8. Disable HTTP
- Beanstalk
- Environment: Supportportalbackend-secured
- Configuration
- Load Balancer -> Edit
- Listeners -> HTTP -> Disable -> Apply
- Test it:
- `http://portal-back-secure.shyshkin.net` -> Timeout
- `https://portal-back-secure.shyshkin.net` -> OK
9. Apply redirection HTTP -> HTTPS
- Enable HTTP back (like in step 8)
- Follow [How can I redirect HTTP requests to HTTPS using an Application Load Balancer?](https://aws.amazon.com/premiumsupport/knowledge-center/elb-redirect-http-to-https-using-alb/)
- EC2 console -> Load Balancer
- Find our ALB
- Listeners -> HTTP -> View/Edit Rules
- Edit -> DEFAULT -> Then -> Edit to
- `Redirect to` -> HTTPS -> 443
- Update
- Test it
- `https://portal-back-secure.shyshkin.net/` -> OK
- `http://portal-back-secure.shyshkin.net/` -> redirect to `https://portal-back-secure.shyshkin.net/` -> OK
10. But now visiting direct LoadBalancer gave an error
- `https://supportportalbackend-secured.eba-wfr5wya3.eu-north-1.elasticbeanstalk.com`
- `NET::ERR_CERT_COMMON_NAME_INVALID`
11. Test with Frontend
- Using **HTTP** `http://portal-back-secure.shyshkin.net` -> ERROR
- `Access to XMLHttpRequest at 'http://portal-back-secure.shyshkin.net/user?size=2147483647' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.`
- Using **HTTPS** `https://portal-back-secure.shyshkin.net` -> OK
#### 40. Secure Communication with HTTPS - Spring Boot Backend - SelfSigned certificate
##### 40.1. Generate SelfSigned certificate
- Follow the steps in [instruction](www.luv2code.com/keytool-steps)
- Generate Key and Self-Signed Certificate
- `keytool -genkeypair -alias securedPortal -keystore src/main/resources/securedPortal-keystore.p12 -keypass secret -storeType PKCS12 -storepass secret -keyalg RSA -keysize 2048 -validity 365 -dname "C=US, ST=Pennsylvania, L=Philadelphia, O=securedPortal, OU=Training Backend, CN=dockerapp.shyshkin.net" -ext "SAN=dns:dockerapp.shyshkin.net"`
- Verify Results
- `keytool -list -v -alias securedPortal -keystore src/main/resources/securedPortal-keystore.p12 -storepass secret`
##### 40.3. Modify Security Group for EC2 instance
- Allow 443 port from anywhere
- Attach `https-443` SG to `docker-ec2` instance
##### 40.4 Deploy Application to `docker-ec2`
- `mvn docker:stop`
- `mvn clean package docker:build docker:start -DskipTests`
- Visit `https://dockerapp.shyshkin.net` -> allow unsecure
##### 40.5 Testing frontend
- `ng build -c production`
- upload to S3
- visit `http://portal.shyshkin.net`
#### 38 Save Profile Images to S3
##### 38.2 Working with S3 (tutorial)
1. Follow Tutorial
- [How to Upload Files to Amazon S3 in Spring Boot](https://www.section.io/engineering-education/spring-boot-amazon-s3/)
2. Create S3 Bucket
- `portal-user-profile-images`
3. Access and secret keys
- My Security Credentials
- will redirect to `https://console.aws.amazon.com/iam/home?region=eu-north-1#/security_credentials`
- Create Access Key
- Access key ID: `AKIA...2GBJ`
- Secret access key: `LUS...H+yuAW`
4. Adding Amazon SDK dependency
- `<dependency>`
- ` <groupId>com.amazonaws</groupId>`
- ` <artifactId>aws-java-sdk</artifactId>`
- ` <version>1.12.75</version>`
- `</dependency>`
5. Create configuration
6. Create ProfileImageService implementation