paulwong

          #

          KEYCLOA+DMariaDB 在LINUX上的安裝

          下載KEYCLOAK與安裝,可參見:
          https://www.janua.fr/how-to-install-keycloak-with-mariadb/

          啟動時配置不通過localhost訪問控制臺:
          #! /bin/bash

          BIN_PATH=$(cd `dirname $0`; pwd)
          IP=10.10.27.69
          KEYCLOAK_OPT="-b ${IP} -Djboss.bind.address.management=${IP} -Dkeycloak.profile.feature.upload_scripts=enabled"
          KEYCLOAK_OPT="${KEYCLOAK_OPT} -Djboss.socket.binding.port-offset=100 -Dkeycloak.frontendUrl=http://${IP}:81/auth "
          #-Dkeycloak.hostname=${IP} -Dkeycloak.httpPort=81 -Dkeycloak.httpsPort=82

          nohup ${BIN_PATH}/bin/standalone.sh ${KEYCLOAK_OPT} > /dev/null &

          更改KEYCLOAK的DATASOURCE時,可直接更改默認的而無需重新配置:
          https://medium.com/@pratik.dandavate/setting-up-keycloak-standalone-with-mysql-database-7ebb614cc229

          KEYCLOAK的JBOSS管理界面地址改為非LOCALHOST:
          -Djboss.bind.address.management=${IP}

          如果是由NGINX過來的訪問,這樣前端的地址是和默認的不一樣,需配置前端URL:
          -Dkeycloak.frontendUrl=http://${IP}:81/auth

          更改JVM大小standalone.conf:
          #
          # Specify options to pass to the Java VM.
          #

          JBOSS_JAVA_SIZING="-server -Xms3G -Xmx3G -Xmn512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m"

          REFERENCE:
          https://www.keycloak.org/docs/latest/server_installation/index.html#_hostname

          posted @ 2022-04-14 15:15 paulwong 閱讀(235) | 評論 (0)編輯 收藏

          UML DIAGRAM資源

          https://www.uml-diagrams.org/uml-25-diagrams.html


          https://www.uml-diagrams.org/index-examples.html

          posted @ 2022-02-19 16:55 paulwong 閱讀(124) | 評論 (0)編輯 收藏

          JENKINS 部署 agularjs

          This article assumes that you have a running Jenkins instance on your Linux machine with a valid domain (not localhost), GitLab and that you are familiar with the Angular framework.

          For Jenkins, please install the GitLab and NodeJS plugins. For simplicity’s sake, this article is going to use simple shell commands to run automated tests and to deploy an app to production.

          ***Note. If you can’t decide where to test all this, there is an article I wrote that might help you: CI/CD Cloud Voyage with Jenkins.

          Configuring Gitlab and Jenkins

          Jenkins: Access Rights to GitLab

          In order to use GitLab with Jenkins, you’ll need to generate an access token in GitLab, which you can do in User menu > Settings > Access tokens

          and configure GitLab Connection on Jenkins by adding the newly generated token.

          In Jenkins, go to Manage Jenkins > Configure system and find the GitLab section.

          To add a token that you previously generated, click on Add by the Credentials input and choose Jenkins. In the credentials dialog, choose GitLab API token in the Kind input and paste your token from GitLab into the API token input field. 

          Jenkins: Configure NodeJSInstaller

          In order to be able to run npm scripts, it is necessary to configure NodeJSInstaller. In Jenkins, go to Manage Jenkins > Global Tool Configuration > NodeJS installations.

          Jenkins: Create CI build for Angular

          In order to be able to run Angular tests and check your code style in Jenkins on the created merge request in GitLab you’ll have to:

          1. Click on the New item link in the Jenkins dashboard

          2. Enter a job name and choose Freestyle project

          3. Choose the GitLab Connection that we’ve just created in the Gitlab Connection section.

          4. Choose Git as your source code management. Enter your repository URL. Create new credentials on Jenkins. These credentials are for cloning the project. You use them to log in to Gitlab.

          5. Next, configure build triggers, i.e. on which GitLab event to run a build. In this particular example, angular-ci-build is going to trigger when a new merge request gets created.

          In this step, we need to go back to GitLab and create a hook that will trigger this build under Settings > Integrations. Copy the URL provided by Jenkins and paste it into the project hook form and finally click Add webhook.

          6. Provide the configured NodeJsInstaller in the global configuration to be able to run npm commands.

          7. And finally, in the Build section choose Add build step > Execute shell. Write shell scripts to test the Angular app code and run tests.

          Click Save and we are good to go. At this point everything should work.

          When you create a new merge request, GitLab should trigger angular-ci-build on Jenkins and you should see status pending on that particular merge request page.

          When Jenkins is done, the status on GitLab should automatically be updated. Depending on whether the build passed or not, the merge button will change color.

          Jenkins: Create CD Build for Angular

          In order to be able to deploy Angular to another Linux machine, we need to:

          Repeat steps 1–4 from Jenkins: Create CI Build for Angular, changing only the name of the build. This time, it can be angular-deploy. 

          5. For step five, we now choose a different configuration for deployment. We are going to run this build when a merge request gets accepted.

          Just like for the CI build, we have to create a new GitLab hook that will hit the Jenkins build endpoint.

          6. This step is also the same as in CI; we need to provide the NodeJSInstaller we already configured globally.

          7. This step is different from CI; this time we don’t have to test and check linting, but only build the application and copy-paste it to another machine with ssh.

          If we are going to do it with ssh like in the example, we need to create a private and public key pair for the Jenkins user on the machine Jenkins is running on. The private key needs to stay on the Jenkins machine, and the public key needs to be copied to the remote machine.

          With the scp command we simply copy our build to the remote machine. In this case, Jenkins does not have permission to put it anywhere but in the user folder. In the last step, we need to ssh into the remote machine and move our files (in this case to /var/www/html).

          Voila, our app is deployed to the production server when the merge request is accepted via Jenkins.

          Angular: Karma Unit Test Runner Configuration

          To run Angular tests on Jenkins, we need to configure some parts of the karma.conf file. Below is the configuration that adds a custom launcher that runs ChromeHeadles.

          module.exports = function(config) {   config.set({     basePath: "",     frameworks: ["jasmine", "@angular-devkit/build-angular"],     plugins: [       require("karma-jasmine"),       require("karma-chrome-launcher"),       require("karma-jasmine-html-reporter"),       require("karma-coverage-istanbul-reporter"),       require("@angular-devkit/build-angular/plugins/karma")     ],     client: {       clearContext: false // leave Jasmine Spec Runner output visible in browser     },     coverageIstanbulReporter: {       dir: require("path").join(__dirname, "../coverage/jenkins-test-app"),       reports: ["html", "lcovonly", "text-summary"],       fixWebpackSourcePaths: true     },     reporters: ["progress", "kjhtml"],     port: 9876,     colors: true,     logLevel: config.LOG_INFO,     autoWatch: true,     browsers: ["Chrome", "ChromeHeadless"],     singleRun: false,     restartOnFileChange: true,     customLaunchers: {       ChromeHeadless: {         base: "Chrome",         flags: [           "--headless",           "--disable-gpu",           "--no-sandbox",           "--remote-debugging-port=9222"         ],                },     }   }); };

          We can then simply store our command in the package.json scripts property.

          On Jenkins, we would now run our tests with npm run test:ci.

           "scripts": {     "ng": "ng",     "start": "ng serve",     "build": "ng build",     "test": "ng test",     "test:ci": "ng test --browsers=ChromeHeadless --watch=false",     "lint": "ng lint",     "e2e": "ng e2e"   },

          I hope you enjoyed this article and that it was helpful in your quest for automating angular deployment and testing.

          posted @ 2022-01-25 11:02 paulwong 閱讀(145) | 評論 (0)編輯 收藏

          SPRING INTEGRATION - 集群選主、分布式鎖

          集群通常是有多個相同的實例,但對于定時任務(wù)場景,只希望有一個實例工作即可,如果這個實例掛了,其他實例可以頂替。

          這個問題的方案則是集群選主,一個集群中,只有一個LEADER,由LEADER負責執(zhí)行定時任務(wù)工作。當LEADER被取消時,會在剩下的實例中再選LEADER。

          持有分布式鎖的實例則是LEADER。

          SPRING INTEGRATION JDBC 則已提供相關(guān)功能。

          pom.xml
                  <dependency>
                     <groupId>org.springframework.integration</groupId>
                     <artifactId>spring-integration-jdbc</artifactId>
                  </dependency>

                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-jdbc</artifactId>
                  </dependency>

                  <dependency>
                     <groupId>org.flywaydb</groupId>
                     <artifactId>flyway-core</artifactId>
                  </dependency>
                  
                  <dependency>
                      <groupId>org.mariadb.jdbc</groupId>
                      <artifactId>mariadb-java-client</artifactId>
                  </dependency>

          LeaderElectionIntegrationConfig.java
          import java.util.List;
          import java.util.concurrent.CopyOnWriteArrayList;

          import javax.sql.DataSource;

          import org.springframework.context.annotation.Bean;
          import org.springframework.context.annotation.Configuration;
          import org.springframework.integration.jdbc.lock.DefaultLockRepository;
          import org.springframework.integration.jdbc.lock.JdbcLockRegistry;
          import org.springframework.integration.jdbc.lock.LockRepository;
          import org.springframework.integration.support.leader.LockRegistryLeaderInitiator;

          import com.paul.integration.leader.ControlBusGateway;
          import com.paul.integration.leader.MyCandidate;

          @Configuration
          public class LeaderElectionIntegrationConfig {
              
              @Bean
              public List<String> needToStartupAdapterList(){
                  return new CopyOnWriteArrayList<>();
              }
              
              @Bean
              public DefaultLockRepository defaultLockRepository(DataSource dataSource){
                  DefaultLockRepository defaultLockRepository =
                          new DefaultLockRepository(dataSource);
          //        defaultLockRepository.setTimeToLive(60_000);
                  return defaultLockRepository;
              }

              @Bean
              public JdbcLockRegistry jdbcLockRegistry(LockRepository lockRepository){
                  return new JdbcLockRegistry(lockRepository);
              }
              
              @Bean
              public MyCandidate myCandidate(
                  ControlBusGateway controlBusGateway,
                  List<String> needToStartupAdapterList
              ) {
                  return new MyCandidate(controlBusGateway, needToStartupAdapterList);
              }
              
              @Bean
              public LockRegistryLeaderInitiator leaderInitiator() {
                  return new LockRegistryLeaderInitiator(
                              jdbcLockRegistry(null), myCandidate(nullnull)
                         );
              }
              
              
          }


          MyCandidate.java
          import java.util.List;

          import org.slf4j.Logger;
          import org.slf4j.LoggerFactory;
          import org.springframework.integration.leader.Context;
          import org.springframework.integration.leader.DefaultCandidate;

          import com.novacredit.mcra.mcracommon.integration.gateway.ControlBusGateway;

          public class MyCandidate extends DefaultCandidate{
              
              private static final Logger LOG = LoggerFactory.getLogger(MyCandidate.class);
              
              private List<String> needToStartupAdapterList;
              
              private ControlBusGateway controlBusGateway;
              
              public MyCandidate(
                  ControlBusGateway controlBusGateway,
                  List<String> needToStartupAdapterList
              ) {
                  this.controlBusGateway = controlBusGateway;
                  this.needToStartupAdapterList = needToStartupAdapterList;
              }
              
              @Override
              public void onGranted(Context context) {
                  super.onGranted(context);
                  LOG.info("*** Leadership granted ***");
                  LOG.info("STARTING MONGODB POLLER");
                  needToStartupAdapterList
                      .forEach(
                          c -> {
          //                    c = "@'testIntegrationFlow.org.springframework.integration.config."
          //                            + "SourcePollingChannelAdapterFactoryBean#0'";
                              String command = c + ".start()";
                              LOG.info("-----{}", command);
                              controlBusGateway.sendCommand(command);
                          }
                       );
                  LOG.info("STARTUP MESSAGE SENT");

              }

              @Override
              public void onRevoked(Context context) {
                  super.onRevoked(context);
                  LOG.info("*** Leadership revoked ***");
                  LOG.info("STOPPING MONGODB POLLER");
                  needToStartupAdapterList
                      .forEach(
                          c -> {
          //                    c = "@'testIntegrationConfig.testIntegrationFlow."
          //                            + "mongoMessageSource.inboundChannelAdapter'";
                              String command = c + ".stop()";
                              LOG.info("-----{}", command);
          //                    controlBusGateway.sendCommand(command);
                          }
                       );
                  LOG.info("SHUTDOWN MESSAGE SENT");
              }

          }


          ControlBusIntegrationConfig.java
          import org.springframework.context.annotation.Bean;
          import org.springframework.context.annotation.Configuration;
          import org.springframework.integration.dsl.IntegrationFlow;
          import org.springframework.integration.dsl.IntegrationFlows;
          import org.springframework.integration.dsl.MessageChannels;
          import org.springframework.integration.gateway.GatewayProxyFactoryBean;
          import org.springframework.integration.handler.LoggingHandler;
          import org.springframework.messaging.MessageChannel;

          import com.paul.integration.gateway.ControlBusGateway;

          @Configuration
          public class ControlBusIntegrationConfig {
              
              @Bean
              public MessageChannel controlBusChannel() {
                  return MessageChannels.direct().get();
              }
              
              @Bean
              public IntegrationFlow controlBusFlow() {
                  return IntegrationFlows.from(controlBusChannel())
                              .log(LoggingHandler.Level.INFO, "controlBusChannel")
                              .controlBus()
                              .get();
              }
              
              @Bean
              public GatewayProxyFactoryBean controlBusGateway() {
                  GatewayProxyFactoryBean gateway = new GatewayProxyFactoryBean(ControlBusGateway.class);
                  gateway.setDefaultRequestChannel(controlBusChannel());
                  gateway.setDefaultRequestTimeout(300l);
                  gateway.setDefaultReplyTimeout(300l);
                  return gateway;
              }
              
          }


          ControlBusGateway.java
          public interface ControlBusGateway {
              
              public void sendCommand(String command);

          }


          各個應(yīng)用實例運行時,其中的LockRegistryLeaderInitiator會自動運行,搶奪LEADER數(shù)據(jù),最終只有一個實例奪取。之后再執(zhí)行MyCandidate中的代碼。







          posted @ 2022-01-20 13:49 paulwong 閱讀(562) | 評論 (0)編輯 收藏

          MONGODB SHELL

          mongo -u admin -p 123456 --authenticationDatabase admin
          use admin
          db.createUser({
           user : "paul",
           pwd : "123456",
           roles : [{role : "readWrite", db : "batch"}]
          })

          #增加權(quán)限
          db.grantRolesToUser( 
            "paul"
            [
              { "role" : "dbOwner",
                "db" : "mcra"
              }
            ]
          )

          posted @ 2022-01-10 11:10 paulwong 閱讀(229) | 評論 (0)編輯 收藏

          OAUTH2 - 4流程如何選擇?





          https://developer.okta.com/docs/concepts/oauth-openid/#what-kind-of-client-are-you-building

          posted @ 2022-01-06 13:37 paulwong 閱讀(144) | 評論 (0)編輯 收藏

          幾個好看的免費UI

          https://demos.creative-tim.com/light-bootstrap-dashboard-angular2/#/dashboard


          https://www.creative-tim.com/product/light-bootstrap-dashboard-angular2

          https://www.creative-tim.com/templates/angular-dashboard-bootstrap

          https://coreui.io/angular/demo/free/2.11.1/#/base/tables

          posted @ 2022-01-04 15:36 paulwong 閱讀(186) | 評論 (0)編輯 收藏

          Easily Secure your Microservices with Keycloak

          https://www.doag.org/formes/pubfiles/11143470/2019-NN-Sebastien_Blanc-Easily_Secure_your_Microservices_with_Keycloak-Praesentation.pdf

          posted @ 2022-01-03 10:03 paulwong 閱讀(152) | 評論 (0)編輯 收藏

          REDHEAD 7 LINUX 軟件集合

          https://www.softwarecollections.org/en/

          不用再GOOGLE尋找安裝方法。

          安裝MYSQL示例:
          # 2. Install the collection:
          $ sudo yum install rh-mariadb103

          # 3. Start using software collections:
          $ scl enable rh-mariadb103 bash

          $ service rh-mariadb103-mariadb start 
          $ mysql
          $ mysqld

          #開機加載命令
          cp /opt/rh/rh-mariadb103/enable /etc/profile.d/rh-mariadb103.sh

          posted @ 2021-12-22 14:28 paulwong 閱讀(202) | 評論 (0)編輯 收藏

          OIDC - KEYCLOAK - 自定義CLIENT SCOPE

          當CLIENT或用戶在KEYCLOAK中成功登錄后,會返回JWT字符串,其中默認含有權(quán)限的信息,但此信息以內(nèi)嵌的方式呈現(xiàn),非常不方便。
          "resource_access": {
              "app-springboot-confidential": {
                "roles": [
                  "user"
                ]
              },
              "test-employee-service": {
                "roles": [
                  "READ_EMPLOYEE"
                ]
              },
              "service-springboot": {
                "roles": [
                  "READ_PRODUCTS"
                ]
              },
              "account": {
                "roles": [
                  "manage-account",
                  "manage-account-links"
                ]
              },
              "test-department-service": {
                "roles": [
                  "READ_DEPARTMENT"
                ]
              }
            }

          • 需要將權(quán)限的信息輸出到一個KEY中,這時可以新增自定義CLIENT SCOPE。Mapper中新增KEYCLOAK已內(nèi)置的【realm roles/client roles】,定義輸出到JTW的字段名:my-roles。
          • 授權(quán)哪些CLIENT可以讀取此CLIENT SCOPE.
          • 在登錄參數(shù)scope中,加入此值:my-roles,這樣在輸出的JWT就會以平面的方式輸出所有roles
          "my-roles": [
              "user",
              "READ_EMPLOYEE",
              "READ_PRODUCTS",
              "manage-account",
              "manage-account-links",
              "READ_DEPARTMENT",
              "offline_access",
              "user"
            ]

          • SPRING SECURITY中取出權(quán)限信息:

          @Bean
              public ReactiveJwtAuthenticationConverter jwtAuthenticationConverter(ObjectMapper objectMapper) {
                  
                  JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
                  jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
                  jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("my-roles");
                  
          //        KeycloakRealmRoleConverter keycloakRealmRoleConverter = new KeycloakRealmRoleConverter(objectMapper);
                  
                  ReactiveJwtGrantedAuthoritiesConverterAdapter reactiveJwtGrantedAuthoritiesConverterAdapter = 
                          new ReactiveJwtGrantedAuthoritiesConverterAdapter(
          //                        new KeycloakRealmRoleConverter(objectMapper);
                                  jwtGrantedAuthoritiesConverter
                              );
                  
                  ReactiveJwtAuthenticationConverter jwtConverter = new ReactiveJwtAuthenticationConverter();
                  jwtConverter.setJwtGrantedAuthoritiesConverter(reactiveJwtGrantedAuthoritiesConverterAdapter);
                  
                  return jwtConverter;
              }

          • 判斷是否有權(quán)限

          ServerHttpSecurity
                      .authorizeExchange(
                          a -> a.pathMatchers("/", "/error").permitAll()
                                .matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
                                .pathMatchers(HttpMethod.GET, "/protected/**").hasRole("READ_DEPARTMENT")
                                .anyExchange()
                                .authenticated()
                       )

          posted @ 2021-12-22 11:15 paulwong 閱讀(760) | 評論 (0)編輯 收藏

          僅列出標題
          共115頁: First 上一頁 4 5 6 7 8 9 10 11 12 下一頁 Last 
          主站蜘蛛池模板: 城口县| 泰兴市| 镇康县| 孟村| 濉溪县| 马公市| 射阳县| 高台县| 东平县| 五原县| 犍为县| 永新县| 盐源县| 盘山县| 崇仁县| 临桂县| 澄迈县| 晋中市| 山西省| 柏乡县| 洮南市| 历史| 平南县| 雷州市| 济南市| 徐州市| 屏东市| 青神县| 西峡县| 曲阳县| 舟曲县| 黄石市| 乌鲁木齐市| 宁波市| 玉溪市| 门头沟区| 威信县| 宁陕县| 砀山县| 高州市| 南陵县|