Popular New Releases in Portal
linkedin-skill-assessments-quizzes
v1.0.4
LinkedInt
1.1 Fixed
ImmersivePortalsMod
xdg-desktop-portal
1.12.4
uPortal
Popular Libraries in Portal
by moodle php
4117 GPL-3.0
Moodle - the world's open source learning platform
by LinusBorg javascript
3537 MIT
A feature-rich Portal Plugin for Vue 2, for rendering DOM outside of a component, anywhere in your app or the entire document.
by Ebazhanov javascript
3467 AGPL-3.0
Full reference of LinkedIn answers 2021 for skill assessments, LinkedIn test, questions and answers (aws-lambda, rest-api, javascript, react, git, html, jquery, mongodb, java, css, python, machine-learning, power-point) linkedin excel test lösungen, linkedin machine learning test
by WICG html
826 NOASSERTION
A proposal for enabling seamless navigations between sites or pages
by hexgnu ruby
755 MIT
Ruby wrapper for the LinkedIn API
by Yenthe666 shell
629 MIT
Odoo install script
by trustedsec python
528 NOASSERTION
This is a tool published for the Citrix ADC (NetScaler) vulnerability. We are only disclosing this due to others publishing the exploit code first.
by dchrastil python
525
A tool to scrape LinkedIn without API restrictions for data reconnaissance
by jprochazka shell
480 MIT
Create your own ADS-B receiver and web portal.
Trending New libraries in Portal
by trustedsec python
528 NOASSERTION
This is a tool published for the Citrix ADC (NetScaler) vulnerability. We are only disclosing this due to others publishing the exploit code first.
by openNDS c
141 GPL-2.0
openNDS provides instant access control of an Internet connection along with a powerful API for development of advanced Captive Portal solutions.
by HewlettPackard python
111 Apache-2.0
Service request portal on top of Ansible Tower/AWX
by arielgs python
74
Automatize conexões no linkedin
by PacktPublishing python
73 MIT
Odoo 14 Development Cookbook - Fourth Edition, published by Packt
by antonbabenko javascript
57 MIT
I'm glad you have passed the certification! I just don't want to see posts about it in my LinkedIn newsfeed.
by fedora-infra css
56 MIT
Self-service user portal for open-source communities to use over FreeIPA.
by ahmedayman4a csharp
56
Download LinkedIn Learning Courses in mp4 format and in the video quality you like with an intuitive UI
by OCA python
50 AGPL-3.0
Odoo modules for a Document Management System
Top Authors in Portal
1
59 Libraries
5857
2
26 Libraries
330
3
20 Libraries
199
4
20 Libraries
117
5
17 Libraries
165
6
14 Libraries
291
7
13 Libraries
99
8
12 Libraries
546
9
9 Libraries
221
10
9 Libraries
233
1
59 Libraries
5857
2
26 Libraries
330
3
20 Libraries
199
4
20 Libraries
117
5
17 Libraries
165
6
14 Libraries
291
7
13 Libraries
99
8
12 Libraries
546
9
9 Libraries
221
10
9 Libraries
233
Trending Kits in Portal
Aktiv Software is committed to helping businesses transform digitally in today's rapidly changing business environment through Odoo ERP services and solutions that meet their unique needs.
Our Services:
Odoo ERP Consulting: https://www.aktivsoftware.com/service/odoo-consulting/
Odoo Customization: https://www.aktivsoftware.com/service/odoo-customization-services/
Odoo Implementation: https://www.aktivsoftware.com/service/odoo-implementation-methodology/
Odoo Development: https://www.aktivsoftware.com/service/odoo-development-services/
Odoo Integration: https://www.aktivsoftware.com/service/odoo-integration-services/
Odoo Migration: https://www.aktivsoftware.com/service/odoo-migration-services/
Odoo Support: https://www.aktivsoftware.com/service/odoo-support/
Odoo Training: https://www.aktivsoftware.com/service/odoo-erp-training/
Trending Discussions on Portal
Azure ASP.NET Core web api returns 404 for proxied multipart/form-data request
Azure Function Runtime Unreachable when deploying from Azure devops pipeline
Kubernetes NodePort is not available on all nodes - Oracle Cloud Infrastructure (OCI)
Invalid Audience when protecting Azure Function with App Service Authentication (EasyAuth) and a Custom OpenID Provider
Diagnostic setting not included in Azure Portal ARM template export
Deploy VUE & Dotnet Core to IIS
Terraform - How to attach SSL certificate stored in Azure KeyVault to an Application Gateway
addEventListener not showing information window on click (JavaScript)
How to define two different entity roles for the same prebuilt Entity (number) in LUIS
HTTPS in Nodejs - error:06065064 digital envelope routines evp_decryptfinal_ex bad decrypt
QUESTION
Azure ASP.NET Core web api returns 404 for proxied multipart/form-data request
Asked 2022-Mar-11 at 08:40I'm new to Azure and trying to set up my nextjs client app and my ASP.NET Core backend app. Everything seems to play well now, except for file uploads. It's working on localhost, but in production the backend returns a 404 web page (attached image) before reaching the actual API endpoint. I've also successfully tested to make a multipart/form-data POST request in Postman from my computer.
The way I implemented this is that I'm proxying the upload from the browser through an api route (client's server side) to the backend. I have to go via the client server side to append a Bearer token from a httpOnly cookie.
I've enabled CORS in Startup.cs:
1app.UseCors(builder => { builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod(); });
2
The frontend and backend apps are running in individual services and I've tried to enable CORS in the Azure portal as well, but there I could only allow origins, not headers and methods? The error message doesn't indicate CORS problems, but I just wanted make sure..
As far as I can see the requests look good, with correct URLs and origins. I suspect I'm missing some config in azure, but I didn't get any further by following the hints in the error message.
Any suggestions to what may cause this? Or where I can start looking. I'm not quite sure where to look for log output for this issue.
ANSWER
Answered 2022-Mar-10 at 06:35Cross-Origin Resource Sharing (CORS) allows JavaScript code running in a browser on an external host to interact with your backend.
To allow all, use "*" and remove all other origins from the list.
I could only allow origins, not headers and methods?
Add the below configuration in your web.config
file to allow headers and methods.
1app.UseCors(builder => { builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod(); });
2<system.webServer>
3 <httpProtocol>
4 <customHeaders>
5 <add name="Access-Control-Allow-Origin" value="*" />
6 <add name="Access-Control-Allow-Headers" value="Content-Type" />
7 <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
8 </customHeaders>
9 </httpProtocol>
10</system.webServer>
11
Add the below snippet in web.config=><system.webServer> =>handlers tag
1app.UseCors(builder => { builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod(); });
2<system.webServer>
3 <httpProtocol>
4 <customHeaders>
5 <add name="Access-Control-Allow-Origin" value="*" />
6 <add name="Access-Control-Allow-Headers" value="Content-Type" />
7 <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
8 </customHeaders>
9 </httpProtocol>
10</system.webServer>
11<?xml version="1.0" encoding="utf-8"?>
12<configuration>
13 <location path="." inheritInChildApplications="false">
14 <system.webServer>
15 <handlers>
16 <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
17 </handlers>
18 <aspNetCore processPath="dotnet" arguments=".\yourURI.dll" stdoutLogEnabled="false" stdoutLogFile="\\?\%home%\LogFiles\stdout" hostingModel="InProcess" />
19 </system.webServer>
20 </location>
21</configuration>
22
- Make sure the routing is done properly
[Route("api/[controller]")] should be in your controller class.
client cache is still pointing to the domain to ols ip address. clear the cache by running the command ipconfig/flushdns
Please refer Custom domain has not been configured inside Azure ,Azure WebApps Custom Domain 404 error - Flush DNS and SO Thread for more information
QUESTION
Azure Function Runtime Unreachable when deploying from Azure devops pipeline
Asked 2022-Feb-28 at 17:26Thanks for taking the time to read. My current setup is as follows:
I have an azure function service up and running, an az function project in visual studio (which I have tested and it runs without issue), a build pipeline in azure devops that deploys a docker image with my function project to an azure container registry.
My problem:
When I try to setup my function service for CI/CD from my devops pipeline, I get the following error on the "functions" tab on my app: "Azure Functions runtime is unreachable". Also none of the functions from my code are listed. In the deployment center however, I get a message "Deployed successfully to production", and it shows my built docker container image name.
Troubleshooting:
In the deployment center of my function app (in the az portal), I set my app to read directly from the azure container registry (using the exact same docker image that my pipeline built earlier), and that worked perfectly - deployment successful and I could see my individual functions name. When I switched back to CI/CD deployment however I got the same problem as earlier.
Trying to see if anyone has had the same problem or could suggest a path forward for getting CI/CD integration working.
I pasted my yaml file below with some names changed for privacy.
1trigger:
2- master
3
4pool:
5 vmImage: 'ubuntu-latest'
6
7variables:
8 project: 'myProjectName'
9 environment: 'prod'
10 dockerfile: '**/Dockerfile'
11 azureResource: 'myScraperFunction'
12 imageName: myScraperFunction
13
14steps:
15- task: Docker@2
16 displayName: Build
17 inputs:
18 command: build
19 containerRegistry: $(azureContainerRegistryName)
20 repository: '$(Build.Repository.Name)-$(project)'
21 tags: '$(Build.BuildNumber)-$(environment)'
22 Dockerfile: $(dockerfile)
23 buildContext: '$(Build.SourcesDirectory)'
24 arguments: --build-arg PAT=$(System.AccessToken)
25
26- task: Docker@2
27 displayName: Push
28 inputs:
29 command: push
30 containerRegistry: $(azureContainerRegistryName)
31 repository: '$(Build.Repository.Name)-$(project)'
32 tags: '$(Build.BuildNumber)-$(environment)'
33 Dockerfile: $(dockerfile)
34
35- task: AzureFunctionAppContainer@1
36 displayName: 'Azure Function App on Container Deploy: $(azureResource)'
37 inputs:
38 azureSubscription: '$(azureSubscription)'
39 appName: $(azureResource)
40 imageName: '$(azureContainerRegistry)/$(imageName):$(Build.BuildNumber)-$(environment)'
41
ANSWER
Answered 2022-Feb-28 at 17:26Configuration/typing issue in yml file. Repository name during build step was hard-coded (I didn't use a variable like what was posted above) and did not match repo name in deploy step because of a spelling error.
QUESTION
Kubernetes NodePort is not available on all nodes - Oracle Cloud Infrastructure (OCI)
Asked 2022-Jan-31 at 14:37I've been trying to get over this but I'm out of ideas for now hence I'm posting the question here.
I'm experimenting with the Oracle Cloud Infrastructure (OCI) and I wanted to create a Kubernetes cluster which exposes some service.
The goal is:
- A running managed Kubernetes cluster (OKE)
- 2 nodes at least
- 1 service that's accessible for external parties
The infra looks the following:
- A VCN for the whole thing
- A private subnet on 10.0.1.0/24
- A public subnet on 10.0.0.0/24
- NAT gateway for the private subnet
- Internet gateway for the public subnet
- Service gateway
- The corresponding security lists for both subnets which I won't share right now unless somebody asks for it
- A containerengine K8S (OKE) cluster in the VCN with public Kubernetes API enabled
- A node pool for the K8S cluster with 2 availability domains and with 2 instances right now. The instances are ARM machines with 1 OCPU and 6GB RAM running Oracle-Linux-7.9-aarch64-2021.12.08-0 images.
- A namespace in the K8S cluster (call it staging for now)
- A deployment which refers to a custom NextJS application serving traffic on port 3000
And now it's the point where I want to expose the service running on port 3000.
I have 2 obvious choices:
- Create a LoadBalancer service in K8S which will spawn a classic Load Balancer in OCI, set up it's listener and set up the backendset referring to the 2 nodes in the cluster, plus it adjusts the subnet security lists to make sure traffic can flow
- Create a Network Load Balancer in OCI and create a NodePort on K8S and manually configure the NLB to the ~same settings as the classic Load Balancer
The first one works perfectly fine but I want to use this cluster with minimal costs so I decided to experiment with option 2, the NLB since it's way cheaper (zero cost).
Long story short, everything works and I can access the NextJS app on the IP of the NLB most of the time but sometimes I couldn't. I decided to look it up what's going on and turned out the NodePort that I exposed in the cluster isn't working how I'd imagine.
The service behind the NodePort is only accessible on the Node that's running the pod in K8S. Assume NodeA is running the service and NodeB is just there chilling. If I try to hit the service on NodeA, everything is fine. But when I try to do the same on NodeB, I don't get a response at all.
That's my problem and I couldn't figure out what could be the issue.
What I've tried so far:
- Switching from ARM machines to AMD ones - no change
- Created a bastion host in the public subnet to test which nodes are responding to requests. Turned out only the node responds that's running the pod.
- Created a regular LoadBalancer in K8S with the same config as the NodePort (in this case OCI will create a classic Load Balancer), that works perfectly
- Tried upgrading to Oracle 8.4 images for the K8S nodes, didn't fix it
- Ran the Node Doctor on the nodes, everything is fine
- Checked the logs of kube-proxy, kube-flannel, core-dns, no error
- Since the cluster consists of 2 nodes, I gave it a try and added one more node and the service was not accessible on the new node either
- Recreated the cluster from scratch
Edit: Some update. I've tried to use a DaemonSet instead of a regular Deployment for the pod to ensure that as a temporary solution, all nodes are running at least one instance of the pod and surprise. The node that was previously not responding to requests on that specific port, it still does not, even though a pod is running on it.
Edit2: Originally I was running the latest K8S version for the cluster (v1.21.5) and I tried downgrading to v1.20.11 and unfortunately the issue is still present.
Edit3: Checked if the NodePort is open on the node that's not responding and it is, at least kube-proxy is listening on it.
1tcp 0 0 0.0.0.0:31600 0.0.0.0:* LISTEN 16671/kube-proxy
2
Edit4:: Tried adding whitelisting iptables rules but didn't change anything.
1tcp 0 0 0.0.0.0:31600 0.0.0.0:* LISTEN 16671/kube-proxy
2[opc@oke-cdvpd5qrofa-nyx7mjtqw4a-svceq4qaiwq-0 ~]$ sudo iptables -P FORWARD ACCEPT
3[opc@oke-cdvpd5qrofa-nyx7mjtqw4a-svceq4qaiwq-0 ~]$ sudo iptables -P INPUT ACCEPT
4[opc@oke-cdvpd5qrofa-nyx7mjtqw4a-svceq4qaiwq-0 ~]$ sudo iptables -P OUTPUT ACCEPT
5
Edit5: Just as a trial, I created a LoadBalancer once more to verify if I'm gone completely mental and I just didn't notice this error when I tried or it really works. Funny thing, it works perfectly fine through the classic load balancer's IP. But when I try to send a request to the nodes directly on the port that was opened for the load balancer (it's 30679 for now). I get response only from the node that's running the pod. From the other, still nothing yet through the load balancer, I get 100% successful responses.
Bonus, here's the iptables from the Node that's not responding to requests, not too sure what to look for:
1tcp 0 0 0.0.0.0:31600 0.0.0.0:* LISTEN 16671/kube-proxy
2[opc@oke-cdvpd5qrofa-nyx7mjtqw4a-svceq4qaiwq-0 ~]$ sudo iptables -P FORWARD ACCEPT
3[opc@oke-cdvpd5qrofa-nyx7mjtqw4a-svceq4qaiwq-0 ~]$ sudo iptables -P INPUT ACCEPT
4[opc@oke-cdvpd5qrofa-nyx7mjtqw4a-svceq4qaiwq-0 ~]$ sudo iptables -P OUTPUT ACCEPT
5[opc@oke-cn44eyuqdoq-n3ewna4fqra-sx5p5dalkuq-1 ~]$ sudo iptables -L
6Chain INPUT (policy ACCEPT)
7target prot opt source destination
8KUBE-NODEPORTS all -- anywhere anywhere /* kubernetes health check service ports */
9KUBE-EXTERNAL-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes externally-visible service portals */
10KUBE-FIREWALL all -- anywhere anywhere
11
12Chain FORWARD (policy ACCEPT)
13target prot opt source destination
14KUBE-FORWARD all -- anywhere anywhere /* kubernetes forwarding rules */
15KUBE-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes service portals */
16KUBE-EXTERNAL-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes externally-visible service portals */
17ACCEPT all -- 10.244.0.0/16 anywhere
18ACCEPT all -- anywhere 10.244.0.0/16
19
20Chain OUTPUT (policy ACCEPT)
21target prot opt source destination
22KUBE-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes service portals */
23KUBE-FIREWALL all -- anywhere anywhere
24
25Chain KUBE-EXTERNAL-SERVICES (2 references)
26target prot opt source destination
27
28Chain KUBE-FIREWALL (2 references)
29target prot opt source destination
30DROP all -- anywhere anywhere /* kubernetes firewall for dropping marked packets */ mark match 0x8000/0x8000
31DROP all -- !loopback/8 loopback/8 /* block incoming localnet connections */ ! ctstate RELATED,ESTABLISHED,DNAT
32
33Chain KUBE-FORWARD (1 references)
34target prot opt source destination
35DROP all -- anywhere anywhere ctstate INVALID
36ACCEPT all -- anywhere anywhere /* kubernetes forwarding rules */ mark match 0x4000/0x4000
37ACCEPT all -- anywhere anywhere /* kubernetes forwarding conntrack pod source rule */ ctstate RELATED,ESTABLISHED
38ACCEPT all -- anywhere anywhere /* kubernetes forwarding conntrack pod destination rule */ ctstate RELATED,ESTABLISHED
39
40Chain KUBE-KUBELET-CANARY (0 references)
41target prot opt source destination
42
43Chain KUBE-NODEPORTS (1 references)
44target prot opt source destination
45
46Chain KUBE-PROXY-CANARY (0 references)
47target prot opt source destination
48
49Chain KUBE-SERVICES (2 references)
50target prot opt source destination
51
Service spec (the running one since it was generated using Terraform):
1tcp 0 0 0.0.0.0:31600 0.0.0.0:* LISTEN 16671/kube-proxy
2[opc@oke-cdvpd5qrofa-nyx7mjtqw4a-svceq4qaiwq-0 ~]$ sudo iptables -P FORWARD ACCEPT
3[opc@oke-cdvpd5qrofa-nyx7mjtqw4a-svceq4qaiwq-0 ~]$ sudo iptables -P INPUT ACCEPT
4[opc@oke-cdvpd5qrofa-nyx7mjtqw4a-svceq4qaiwq-0 ~]$ sudo iptables -P OUTPUT ACCEPT
5[opc@oke-cn44eyuqdoq-n3ewna4fqra-sx5p5dalkuq-1 ~]$ sudo iptables -L
6Chain INPUT (policy ACCEPT)
7target prot opt source destination
8KUBE-NODEPORTS all -- anywhere anywhere /* kubernetes health check service ports */
9KUBE-EXTERNAL-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes externally-visible service portals */
10KUBE-FIREWALL all -- anywhere anywhere
11
12Chain FORWARD (policy ACCEPT)
13target prot opt source destination
14KUBE-FORWARD all -- anywhere anywhere /* kubernetes forwarding rules */
15KUBE-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes service portals */
16KUBE-EXTERNAL-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes externally-visible service portals */
17ACCEPT all -- 10.244.0.0/16 anywhere
18ACCEPT all -- anywhere 10.244.0.0/16
19
20Chain OUTPUT (policy ACCEPT)
21target prot opt source destination
22KUBE-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes service portals */
23KUBE-FIREWALL all -- anywhere anywhere
24
25Chain KUBE-EXTERNAL-SERVICES (2 references)
26target prot opt source destination
27
28Chain KUBE-FIREWALL (2 references)
29target prot opt source destination
30DROP all -- anywhere anywhere /* kubernetes firewall for dropping marked packets */ mark match 0x8000/0x8000
31DROP all -- !loopback/8 loopback/8 /* block incoming localnet connections */ ! ctstate RELATED,ESTABLISHED,DNAT
32
33Chain KUBE-FORWARD (1 references)
34target prot opt source destination
35DROP all -- anywhere anywhere ctstate INVALID
36ACCEPT all -- anywhere anywhere /* kubernetes forwarding rules */ mark match 0x4000/0x4000
37ACCEPT all -- anywhere anywhere /* kubernetes forwarding conntrack pod source rule */ ctstate RELATED,ESTABLISHED
38ACCEPT all -- anywhere anywhere /* kubernetes forwarding conntrack pod destination rule */ ctstate RELATED,ESTABLISHED
39
40Chain KUBE-KUBELET-CANARY (0 references)
41target prot opt source destination
42
43Chain KUBE-NODEPORTS (1 references)
44target prot opt source destination
45
46Chain KUBE-PROXY-CANARY (0 references)
47target prot opt source destination
48
49Chain KUBE-SERVICES (2 references)
50target prot opt source destination
51{
52 "apiVersion": "v1",
53 "kind": "Service",
54 "metadata": {
55 "creationTimestamp": "2022-01-28T09:13:33Z",
56 "name": "web-staging-service",
57 "namespace": "web-staging",
58 "resourceVersion": "22542",
59 "uid": "c092f99b-7c72-4c32-bf27-ccfa1fe92a79"
60 },
61 "spec": {
62 "clusterIP": "10.96.99.112",
63 "clusterIPs": [
64 "10.96.99.112"
65 ],
66 "externalTrafficPolicy": "Cluster",
67 "ipFamilies": [
68 "IPv4"
69 ],
70 "ipFamilyPolicy": "SingleStack",
71 "ports": [
72 {
73 "nodePort": 31600,
74 "port": 3000,
75 "protocol": "TCP",
76 "targetPort": 3000
77 }
78 ],
79 "selector": {
80 "app": "frontend"
81 },
82 "sessionAffinity": "None",
83 "type": "NodePort"
84 },
85 "status": {
86 "loadBalancer": {}
87 }
88}
89
Any ideas are appreciated. Thanks guys.
ANSWER
Answered 2022-Jan-31 at 12:06Might not be the ideal fix, but can you try changing the externalTrafficPolicy to Local. This would prevent the health check on the nodes which don't run the application to fail. This way the traffic will only be forwarded to the node where the application is . Setting externalTrafficPolicy to local is also a requirement to preserve source IP of the connection. Also, can you share the health check config for both NLB and LB that you are using. When you change the externalTrafficPolicy, note that the health check for LB would change and the same needs to be applied to NLB.
Edit: Also note that you need a security list/ network security group added to your node subnet/nodepool, which allows traffic on all protocols from the worker node subnet.
QUESTION
Invalid Audience when protecting Azure Function with App Service Authentication (EasyAuth) and a Custom OpenID Provider
Asked 2021-Dec-19 at 18:10I have an Azure Function (tried both Windows and Linux Consumption) using Azure App Service Authentication (Easy Auth) with a custom OpenId Connect provider to authenticate my Azure Function with an http trigger.
I configured a client in my Identity Provider (based on Duende Identity Server), acquired a token and then sent a request to the Azure Function (contains just the code that is initially created by Visual Studio when creating a Function App project).
This is the configuration I made in the Azure Portal:
When I now send the request to the Azure function endpoint I always get the following error:
1{
2 "code": 401,
3 "message": "IDX10214: Audience validation failed. Audiences: 'System.String'. Did not match: validationParameters.ValidAudience: 'System.String' or validationParameters.ValidAudiences: 'System.String'."
4}
5
I didn't find any option to configure an audience in the Azure Portal or via the Azure CLI and there's no documentation on how the audience has to look like to be accepted.
I also found a Github issue describing basically the same error: https://github.com/MicrosoftDocs/azure-docs/issues/72019
How can I either see what valid audiences are, configure a valid audience in Azure AppService Authentication or fix that error altogether?
PS: If I disable the authentication in Azure obviously the function is triggered and returns a response.
ANSWER
Answered 2021-Dec-19 at 18:10You should try using the Client ID as the scope while generating the token.
In some cases appending /.default
to the scope helps. Example eda25bbe-a724-43ba-8fa3-8977aba6fb36/.default
.
QUESTION
Diagnostic setting not included in Azure Portal ARM template export
Asked 2021-Dec-17 at 08:39I create a Diagnostic Settings for a KeyVault resource in Azure portal. DS properties are Metrics = AllMetrics and Destination is a predefined Log Analytics Workspace. When I do an export (Automation - Export Template) from Portal, nothing from the diagnostic setting is included in the generated ARM json. I've noticed the same behavior when resource is an App Service.
Is this by design? A bug? Any other way to get the ARM json for the diagnostic setting I've defined?
ANSWER
Answered 2021-Dec-17 at 08:39I tried the same in my environment and seems we cannot export the diagnostics settings for any service like key vault, app service , storage account etc
when we try to export the template for automation . But there are some sample Diagnostics settings Templates for few resources provided in Microsoft Documentation.
So , as per your settings it will something like below which I have tested by deploying :
1{
2 "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
3 "contentVersion": "1.0.0.0",
4 "parameters": {
5 "settingName": {
6 "type": "String",
7 "defaultValue": "testdsansuman"
8 },
9 "vaultName": {
10 "type": "String",
11 "defaultValue": "ansumantestkv1234"
12 },
13 "workspaceName": {
14 "type": "String",
15 "defaultValue": "ansumantestlog"
16 }
17 },
18 "resources": [
19 {
20 "type": "Microsoft.KeyVault/vaults/providers/diagnosticSettings",
21 "apiVersion": "2017-05-01-preview",
22 "name": "[concat(parameters('vaultName'), '/Microsoft.Insights/', parameters('settingName'))]",
23 "dependsOn": [],
24 "properties": {
25 "workspaceId": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('WorkspaceName'))]",
26
27 "metrics": [
28 {
29 "category": "AllMetrics",
30 "enabled": true
31 }
32 ]
33 }
34 }
35 ]
36 }
37
QUESTION
Deploy VUE & Dotnet Core to IIS
Asked 2021-Nov-25 at 11:57I'm trying to deploy my VUE portal & it's Dotnet backend API on the same IIS site. I was only able to host the each on it's own site on IIS, but I want to host them both on the same site. Can someone please advise how?
ANSWER
Answered 2021-Nov-25 at 11:57- Download & Install:
- .NET Core Hosting Bundle
- Microsoft URL Rewrite
- Restart the IIS service.
- Setup new IIS Website:
- Open IIS on the server.
- Right click the Sites folder and select "Add website"
- enter site name
- set the physical path to the Vue.js app directory
- leave the host name empty → click "OK".
- Right click the new site and select "Add Application"
- enter the alias "api" (without quotes)
- set the physical path to the ASP.NET Core api directory
- click "OK".
- In Application Pools
- right click the app pool for the new site → "Basic Settings"
- change the .NET CLR version to 'No Managed Code'.
- right click the app pool for the new site → "Advanced Settings"
- set ‘Identity’: LocalSystem
- Make sure "web.config" is as given in the article below! Vue.js + ASP.NET
& inside the Vue.js front-end folder
additional resources:
QUESTION
Terraform - How to attach SSL certificate stored in Azure KeyVault to an Application Gateway
Asked 2021-Nov-24 at 10:51I have a Terraform script that create an Azure Key Vault, imports my SSL certificate (3DES .pfx file with a password), and creates an Application Gateway with a HTTP listener. I'm trying to change this to a HTTPS listener that uses my SSL certificate from KeyVault.
I've stepped through this process manually in Azure Portal and I have this working with PowerShell. Unfortunately I don't find Terraform's documentation clear on how this is supposed to be achieved.
Here are relevant snippets of my Application Gateway and certificate resources:
1resource "azurerm_application_gateway" "appgw" {
2 name = "my-appgw"
3 location = "australiaeast"
4 resource_group_name = "my-rg"
5
6 http_listener {
7 protocol = "https"
8 ssl_certificate_name = "appgw-listener-cert"
9 ...
10 }
11
12 identity {
13 type = "UserAssigned"
14 identity_ids = [azurerm_user_assigned_identity.appgw_uaid.id]
15 }
16
17 ssl_certificate {
18 key_vault_secret_id = azurerm_key_vault_certificate.ssl_cert.secret_id
19 name = "appgw-listener-cert"
20 }
21
22 ...
23}
24
25resource "azurerm_key_vault" "kv" {
26 name = "my-kv"
27 location = "australiaeast"
28 resource_group_name = "my-rg"
29 ...
30 access_policy {
31 object_id = data.azurerm_client_config.current.object_id
32 tenant_id = data.azurerm_client_config.current.tenant_id
33
34 certificate_permissions = [
35 "Create",
36 "Delete",
37 "DeleteIssuers",
38 "Get",
39 "GetIssuers",
40 "Import",
41 "List",
42 "ListIssuers",
43 "ManageContacts",
44 "ManageIssuers",
45 "Purge",
46 "SetIssuers",
47 "Update"
48 ]
49
50 key_permissions = [
51 "Backup",
52 "Create",
53 "Decrypt",
54 "Delete",
55 "Encrypt",
56 "Get",
57 "Import",
58 "List",
59 "Purge",
60 "Recover",
61 "Restore",
62 "Sign",
63 "UnwrapKey",
64 "Update",
65 "Verify",
66 "WrapKey"
67 ]
68
69 secret_permissions = [
70 "Backup",
71 "Delete",
72 "Get",
73 "List",
74 "Purge",
75 "Restore",
76 "Restore",
77 "Set"
78 ]
79 }
80
81 access_policy {
82 object_id = azurerm_user_assigned_identity.uaid_appgw.principal_id
83 tenant_id = data.azurerm_client_config.current.tenant_id
84
85 secret_permissions = [
86 "Get"
87 ]
88 }
89}
90
91resource "azurerm_key_vault_certificate" "ssl_cert" {
92 name = "my-ssl-cert"
93 key_vault_id = azurerm_key_vault.kv.id
94
95 certificate {
96 # These are stored as sensitive variables in Terraform Cloud
97 # ssl_cert_b64 value was retrieved by: $ cat my-ssl-cert.pfx | base64 > o.txt
98 contents = var.ssl_cert_b64
99 password = var.ssl_cert_passwd
100 }
101
102 certificate_policy {
103 issuer_parameters {
104 name = "Unknown"
105 }
106
107 key_properties {
108 exportable = false
109 key_size = 2048
110 key_type = "RSA"
111 reuse_key = false
112 }
113
114 secret_properties {
115 content_type = "application/x-pkcs12"
116 }
117 }
118}
119
Here is the (sanitised) error I get in Terraform Cloud:
Error: waiting for create/update of Application Gateway: (Name "my-appgw" / Resource Group "my-rg"): Code="ApplicationGatewayKeyVaultSecretException" Message="Problem occured while accessing and validating KeyVault Secrets associated with Application Gateway '/subscriptions/1324/resourceGroups/my-rg/providers/Microsoft.Network/applicationGateways/my-appgw'. See details below:" Details=[{"code":"ApplicationGatewaySslCertificateDoesNotHavePrivateKey","message":"Certificate /subscriptions/1324/resourceGroups/my-rg/providers/Microsoft.Network/applicationGateways/my-appgw/sslCertificates/appgw-listener-cert does not have Private Key."}]
I downloaded the certificate from Key Vault and it appears to be a valid, not corrupted or otherwise broken. I don't understand why the error says it doesn't have a Private Key.
Can someone point out what I've missed or I'm doing wrong?
ANSWER
Answered 2021-Sep-16 at 10:10The issue is that there isn't any access policy defined for the app gateway in the keyvault for which it not able to get the certififcate.
So, inorder to resolve this , you have to add an acess policy for the managed identity that is being used by the application gateway. So, after creating managed identity and before using in application gateway, you have to use something like below:
1resource "azurerm_application_gateway" "appgw" {
2 name = "my-appgw"
3 location = "australiaeast"
4 resource_group_name = "my-rg"
5
6 http_listener {
7 protocol = "https"
8 ssl_certificate_name = "appgw-listener-cert"
9 ...
10 }
11
12 identity {
13 type = "UserAssigned"
14 identity_ids = [azurerm_user_assigned_identity.appgw_uaid.id]
15 }
16
17 ssl_certificate {
18 key_vault_secret_id = azurerm_key_vault_certificate.ssl_cert.secret_id
19 name = "appgw-listener-cert"
20 }
21
22 ...
23}
24
25resource "azurerm_key_vault" "kv" {
26 name = "my-kv"
27 location = "australiaeast"
28 resource_group_name = "my-rg"
29 ...
30 access_policy {
31 object_id = data.azurerm_client_config.current.object_id
32 tenant_id = data.azurerm_client_config.current.tenant_id
33
34 certificate_permissions = [
35 "Create",
36 "Delete",
37 "DeleteIssuers",
38 "Get",
39 "GetIssuers",
40 "Import",
41 "List",
42 "ListIssuers",
43 "ManageContacts",
44 "ManageIssuers",
45 "Purge",
46 "SetIssuers",
47 "Update"
48 ]
49
50 key_permissions = [
51 "Backup",
52 "Create",
53 "Decrypt",
54 "Delete",
55 "Encrypt",
56 "Get",
57 "Import",
58 "List",
59 "Purge",
60 "Recover",
61 "Restore",
62 "Sign",
63 "UnwrapKey",
64 "Update",
65 "Verify",
66 "WrapKey"
67 ]
68
69 secret_permissions = [
70 "Backup",
71 "Delete",
72 "Get",
73 "List",
74 "Purge",
75 "Restore",
76 "Restore",
77 "Set"
78 ]
79 }
80
81 access_policy {
82 object_id = azurerm_user_assigned_identity.uaid_appgw.principal_id
83 tenant_id = data.azurerm_client_config.current.tenant_id
84
85 secret_permissions = [
86 "Get"
87 ]
88 }
89}
90
91resource "azurerm_key_vault_certificate" "ssl_cert" {
92 name = "my-ssl-cert"
93 key_vault_id = azurerm_key_vault.kv.id
94
95 certificate {
96 # These are stored as sensitive variables in Terraform Cloud
97 # ssl_cert_b64 value was retrieved by: $ cat my-ssl-cert.pfx | base64 > o.txt
98 contents = var.ssl_cert_b64
99 password = var.ssl_cert_passwd
100 }
101
102 certificate_policy {
103 issuer_parameters {
104 name = "Unknown"
105 }
106
107 key_properties {
108 exportable = false
109 key_size = 2048
110 key_type = "RSA"
111 reuse_key = false
112 }
113
114 secret_properties {
115 content_type = "application/x-pkcs12"
116 }
117 }
118}
119provider "azurerm" {
120 features{}
121}
122data "azurerm_client_config" "current" {}
123
124resource "azurerm_user_assigned_identity" "base" {
125 resource_group_name = "yourresourcegroup"
126 location = "resourcegrouplocation"
127 name = "mi-appgw-keyvault"
128}
129
130data "azurerm_key_vault" "example"{
131 name = "testansumankeyvault-01"
132 resource_group_name = "yourresourcegroup"
133}
134resource "azurerm_key_vault_access_policy" "example" {
135 key_vault_id = data.azurerm_key_vault.example.id
136 tenant_id = data.azurerm_client_config.current.tenant_id
137 object_id = azurerm_user_assigned_identity.base.principal_id
138
139 key_permissions = [
140 "Get",
141 ]
142
143 certificate_permissions = [
144 "Get",
145 ]
146
147 secret_permissions = [
148 "Get",
149 ]
150}
151
So , Only after the above is done you can use something similar to below as per your requirement:
1resource "azurerm_application_gateway" "appgw" {
2 name = "my-appgw"
3 location = "australiaeast"
4 resource_group_name = "my-rg"
5
6 http_listener {
7 protocol = "https"
8 ssl_certificate_name = "appgw-listener-cert"
9 ...
10 }
11
12 identity {
13 type = "UserAssigned"
14 identity_ids = [azurerm_user_assigned_identity.appgw_uaid.id]
15 }
16
17 ssl_certificate {
18 key_vault_secret_id = azurerm_key_vault_certificate.ssl_cert.secret_id
19 name = "appgw-listener-cert"
20 }
21
22 ...
23}
24
25resource "azurerm_key_vault" "kv" {
26 name = "my-kv"
27 location = "australiaeast"
28 resource_group_name = "my-rg"
29 ...
30 access_policy {
31 object_id = data.azurerm_client_config.current.object_id
32 tenant_id = data.azurerm_client_config.current.tenant_id
33
34 certificate_permissions = [
35 "Create",
36 "Delete",
37 "DeleteIssuers",
38 "Get",
39 "GetIssuers",
40 "Import",
41 "List",
42 "ListIssuers",
43 "ManageContacts",
44 "ManageIssuers",
45 "Purge",
46 "SetIssuers",
47 "Update"
48 ]
49
50 key_permissions = [
51 "Backup",
52 "Create",
53 "Decrypt",
54 "Delete",
55 "Encrypt",
56 "Get",
57 "Import",
58 "List",
59 "Purge",
60 "Recover",
61 "Restore",
62 "Sign",
63 "UnwrapKey",
64 "Update",
65 "Verify",
66 "WrapKey"
67 ]
68
69 secret_permissions = [
70 "Backup",
71 "Delete",
72 "Get",
73 "List",
74 "Purge",
75 "Restore",
76 "Restore",
77 "Set"
78 ]
79 }
80
81 access_policy {
82 object_id = azurerm_user_assigned_identity.uaid_appgw.principal_id
83 tenant_id = data.azurerm_client_config.current.tenant_id
84
85 secret_permissions = [
86 "Get"
87 ]
88 }
89}
90
91resource "azurerm_key_vault_certificate" "ssl_cert" {
92 name = "my-ssl-cert"
93 key_vault_id = azurerm_key_vault.kv.id
94
95 certificate {
96 # These are stored as sensitive variables in Terraform Cloud
97 # ssl_cert_b64 value was retrieved by: $ cat my-ssl-cert.pfx | base64 > o.txt
98 contents = var.ssl_cert_b64
99 password = var.ssl_cert_passwd
100 }
101
102 certificate_policy {
103 issuer_parameters {
104 name = "Unknown"
105 }
106
107 key_properties {
108 exportable = false
109 key_size = 2048
110 key_type = "RSA"
111 reuse_key = false
112 }
113
114 secret_properties {
115 content_type = "application/x-pkcs12"
116 }
117 }
118}
119provider "azurerm" {
120 features{}
121}
122data "azurerm_client_config" "current" {}
123
124resource "azurerm_user_assigned_identity" "base" {
125 resource_group_name = "yourresourcegroup"
126 location = "resourcegrouplocation"
127 name = "mi-appgw-keyvault"
128}
129
130data "azurerm_key_vault" "example"{
131 name = "testansumankeyvault-01"
132 resource_group_name = "yourresourcegroup"
133}
134resource "azurerm_key_vault_access_policy" "example" {
135 key_vault_id = data.azurerm_key_vault.example.id
136 tenant_id = data.azurerm_client_config.current.tenant_id
137 object_id = azurerm_user_assigned_identity.base.principal_id
138
139 key_permissions = [
140 "Get",
141 ]
142
143 certificate_permissions = [
144 "Get",
145 ]
146
147 secret_permissions = [
148 "Get",
149 ]
150}
151data "azurerm_user_assigned_identity" "example" {
152 name = "mi-appgw-keyvault"
153 resource_group_name = "yourresourcegroup"
154}
155data "azurerm_key_vault" "example"{
156 name = "testansumankeyvault-01"
157 resource_group_name = "yourresourcegroup"
158}
159resource "azurerm_application_gateway" "appgw" {
160 name = "my-appgw"
161 location = "australiaeast"
162 resource_group_name = "my-rg"
163
164 http_listener {
165 protocol = "https"
166 ssl_certificate_name = "appgw-listener-cert"
167 ...
168 }
169
170 identity {
171 type = "UserAssigned"
172 identity_ids = [data.azurerm_user_assigned_identity.example.id]
173 }
174
175 ssl_certificate {
176 key_vault_secret_id = azurerm_key_vault_certificate.ssl_cert.secret_id
177 name = "appgw-listener-cert"
178 }
179
180 ...
181}
182
183data "azurerm_key_vault_certificate" "example" {
184 name = "secret-sauce"
185 key_vault_id = data.azurerm_key_vault.example.id
186}
187
Note:
I have used exisitng keyvault to set the keyvault access policy for testing and also a exisitng certificate in keyvault. If you are creating new then please use 2 deployments:
- Deploy Keyvault,managed_identity ,access policy and certificate for keyvault first.
- Then use data sources for keyvault, managed identity and certificate and then deploy the application gateway with ssl certificate referencing from keyvault.
QUESTION
addEventListener not showing information window on click (JavaScript)
Asked 2021-Nov-12 at 20:12I'm working on a web application for a disaster management lab assignment that is using the Google Places and Maps JavaScript API. The goal is to have markers on the map which are attached to an event listener which is supposed to show an information window with the data about a disaster report. However, the window is not showing up when I click on the marker. The pointer finger icon shows when I hover over a point, yet no information window appears when I click on the marker. There are zero errors in the dev console when I run it through IntelliJ and Tomcat, and I tried changing addListener
to addEventListener
but it still doesn't work. I will post my code below but let me know if you need anything else to help. For security reasons, I have replaced my API key with MY_API_KEY
, so I guess you will have to have access to the Google API's yourself in order to help so I apologize for that. Thanks!
P.S.
When I tried creating the snippet it came up with the following error which I'm unsure where the error is coming from because there is no line 302 in the JS code:
{ "message": "Uncaught SyntaxError: Unexpected end of input", "filename": "https://stacksnippets.net/js", "lineno": 302, "colno": 5 }
Here's what the information window is supposed to look like:
1//loadform.js
2function onSelectReportType(ele) {
3 var form = $(ele).parent().parent();
4 var label = $(form).find(".additional_msg");
5 var select = $(form).find(".additional_msg_select");
6
7 switch (ele.value) {
8 case "donation":
9 case "request":
10 label.text("Resource Type:");
11 select.find('option').remove();
12 select.append($("<option></option>")
13 .attr("value", "")
14 .text("Choose the resource type"));
15 selectValues = ['water', 'food', 'money', 'medicine', 'cloth',
16 'rescue/volunteer'
17 ];
18 $.each(selectValues, function(index, value) {
19 select.append($("<option></option>")
20 .attr("value", value)
21 .text(value));
22 });
23 break;
24 case "damage":
25 label.text("Damage Type:");
26 select.find('option').remove();
27 select.append($("<option></option>")
28 .attr("value", "")
29 .text("Choose the damage type"));
30 selectValues = ['polution', 'building damage', 'road damage', 'casualty',
31 'other'
32 ];
33 $.each(selectValues, function(index, value) {
34 select.append($("<option></option>")
35 .attr("value", value)
36 .text(value));
37 });
38 break;
39 default:
40 $(form).find(".additional_msg_div").css("visibility", "hidden");
41 return;
42 }
43 $(form).find(".additional_msg_div").css("visibility", "visible");
44
45
46 //loadmap.js
47 var map;
48 var infowindow = new google.maps.InfoWindow();
49
50 function initialization() {
51 showAllReports();
52 }
53
54 function showAllReports() {
55 $.ajax({
56 url: 'HttpServlet',
57 type: 'POST',
58 data: {
59 "tab_id": "1"
60 },
61 success: function(reports) {
62 mapInitialization(reports);
63 },
64 error: function(xhr, status, error) {
65 alert("An AJAX error occured: " + status + "\nError: " + error);
66 }
67 });
68 }
69
70 function mapInitialization(reports) {
71 var mapOptions = {
72 mapTypeId: google.maps.MapTypeId.ROADMAP, // Set the type of Map
73 };
74
75 // Render the map within the empty div
76 map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
77
78 var bounds = new google.maps.LatLngBounds();
79
80 $.each(reports, function(i, e) {
81 var long = Number(e['longitude']);
82 var lat = Number(e['latitude']);
83 var latlng = new google.maps.LatLng(lat, long);
84
85 bounds.extend(latlng);
86
87 // Create the infoWindow content
88 var contentStr = '<h4>Report Details</h4><hr>';
89 contentStr += '<p><b>' + 'Disaster' + ':</b>&nbsp' + e['disaster'] + '</p>';
90 contentStr += '<p><b>' + 'Report Type' + ':</b>&nbsp' + e['report_type'] +
91 '</p>';
92 if (e['report_type'] == 'request' || e['report_type'] == 'donation') {
93 contentStr += '<p><b>' + 'Resource Type' + ':</b>&nbsp' +
94 e['resource_type'] + '</p>';
95 } else if (e['report_type'] == 'damage') {
96 contentStr += '<p><b>' + 'Damage Type' + ':</b>&nbsp' + e['damage_type'] +
97 '</p>';
98 }
99 contentStr += '<p><b>' + 'Timestamp' + ':</b>&nbsp' +
100 e['time_stamp'].substring(0, 19) + '</p>';
101 if ('message' in e) {
102 contentStr += '<p><b>' + 'Message' + ':</b>&nbsp' + e['message'] + '</p>';
103 }
104
105 // Create the marker
106 var marker = new google.maps.Marker({ // Set the marker
107 position: latlng, // Position marker to coordinates
108 map: map, // assign the market to our map variable
109 customInfo: contentStr,
110 });
111
112 // Add a Click Listener to the marker
113 google.maps.event.addEventListener(marker, 'click', function() {
114 // use 'customInfo' to customize infoWindow
115 infowindow.setContent(marker['customInfo']);
116 infowindow.open(map, marker); // Open InfoWindow
117 });
118
119 });
120
121 map.fitBounds(bounds);
122
123 }
124
125
126 //Execute our 'initialization' function once the page has loaded.
127 google.maps.event.addDomListener(window, 'load', initialization);
1//loadform.js
2function onSelectReportType(ele) {
3 var form = $(ele).parent().parent();
4 var label = $(form).find(".additional_msg");
5 var select = $(form).find(".additional_msg_select");
6
7 switch (ele.value) {
8 case "donation":
9 case "request":
10 label.text("Resource Type:");
11 select.find('option').remove();
12 select.append($("<option></option>")
13 .attr("value", "")
14 .text("Choose the resource type"));
15 selectValues = ['water', 'food', 'money', 'medicine', 'cloth',
16 'rescue/volunteer'
17 ];
18 $.each(selectValues, function(index, value) {
19 select.append($("<option></option>")
20 .attr("value", value)
21 .text(value));
22 });
23 break;
24 case "damage":
25 label.text("Damage Type:");
26 select.find('option').remove();
27 select.append($("<option></option>")
28 .attr("value", "")
29 .text("Choose the damage type"));
30 selectValues = ['polution', 'building damage', 'road damage', 'casualty',
31 'other'
32 ];
33 $.each(selectValues, function(index, value) {
34 select.append($("<option></option>")
35 .attr("value", value)
36 .text(value));
37 });
38 break;
39 default:
40 $(form).find(".additional_msg_div").css("visibility", "hidden");
41 return;
42 }
43 $(form).find(".additional_msg_div").css("visibility", "visible");
44
45
46 //loadmap.js
47 var map;
48 var infowindow = new google.maps.InfoWindow();
49
50 function initialization() {
51 showAllReports();
52 }
53
54 function showAllReports() {
55 $.ajax({
56 url: 'HttpServlet',
57 type: 'POST',
58 data: {
59 "tab_id": "1"
60 },
61 success: function(reports) {
62 mapInitialization(reports);
63 },
64 error: function(xhr, status, error) {
65 alert("An AJAX error occured: " + status + "\nError: " + error);
66 }
67 });
68 }
69
70 function mapInitialization(reports) {
71 var mapOptions = {
72 mapTypeId: google.maps.MapTypeId.ROADMAP, // Set the type of Map
73 };
74
75 // Render the map within the empty div
76 map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
77
78 var bounds = new google.maps.LatLngBounds();
79
80 $.each(reports, function(i, e) {
81 var long = Number(e['longitude']);
82 var lat = Number(e['latitude']);
83 var latlng = new google.maps.LatLng(lat, long);
84
85 bounds.extend(latlng);
86
87 // Create the infoWindow content
88 var contentStr = '<h4>Report Details</h4><hr>';
89 contentStr += '<p><b>' + 'Disaster' + ':</b>&nbsp' + e['disaster'] + '</p>';
90 contentStr += '<p><b>' + 'Report Type' + ':</b>&nbsp' + e['report_type'] +
91 '</p>';
92 if (e['report_type'] == 'request' || e['report_type'] == 'donation') {
93 contentStr += '<p><b>' + 'Resource Type' + ':</b>&nbsp' +
94 e['resource_type'] + '</p>';
95 } else if (e['report_type'] == 'damage') {
96 contentStr += '<p><b>' + 'Damage Type' + ':</b>&nbsp' + e['damage_type'] +
97 '</p>';
98 }
99 contentStr += '<p><b>' + 'Timestamp' + ':</b>&nbsp' +
100 e['time_stamp'].substring(0, 19) + '</p>';
101 if ('message' in e) {
102 contentStr += '<p><b>' + 'Message' + ':</b>&nbsp' + e['message'] + '</p>';
103 }
104
105 // Create the marker
106 var marker = new google.maps.Marker({ // Set the marker
107 position: latlng, // Position marker to coordinates
108 map: map, // assign the market to our map variable
109 customInfo: contentStr,
110 });
111
112 // Add a Click Listener to the marker
113 google.maps.event.addEventListener(marker, 'click', function() {
114 // use 'customInfo' to customize infoWindow
115 infowindow.setContent(marker['customInfo']);
116 infowindow.open(map, marker); // Open InfoWindow
117 });
118
119 });
120
121 map.fitBounds(bounds);
122
123 }
124
125
126 //Execute our 'initialization' function once the page has loaded.
127 google.maps.event.addDomListener(window, 'load', initialization);html,
128body {
129 background-color: #f5f5f5;
130}
131
132body {
133 padding-top: 50px;
134}
135
136.container-fluid,
137.row {
138 background-color: #f5f5f5;
139}
140
141.sidebar {
142 padding: 12px;
143 background-color: #f5f5f5;
144}
145
146form {
147 padding-top: 12px;
148}
149
150#map-canvas {
151 height: 100%;
152 position: absolute;
153 right: 0;
154}
1//loadform.js
2function onSelectReportType(ele) {
3 var form = $(ele).parent().parent();
4 var label = $(form).find(".additional_msg");
5 var select = $(form).find(".additional_msg_select");
6
7 switch (ele.value) {
8 case "donation":
9 case "request":
10 label.text("Resource Type:");
11 select.find('option').remove();
12 select.append($("<option></option>")
13 .attr("value", "")
14 .text("Choose the resource type"));
15 selectValues = ['water', 'food', 'money', 'medicine', 'cloth',
16 'rescue/volunteer'
17 ];
18 $.each(selectValues, function(index, value) {
19 select.append($("<option></option>")
20 .attr("value", value)
21 .text(value));
22 });
23 break;
24 case "damage":
25 label.text("Damage Type:");
26 select.find('option').remove();
27 select.append($("<option></option>")
28 .attr("value", "")
29 .text("Choose the damage type"));
30 selectValues = ['polution', 'building damage', 'road damage', 'casualty',
31 'other'
32 ];
33 $.each(selectValues, function(index, value) {
34 select.append($("<option></option>")
35 .attr("value", value)
36 .text(value));
37 });
38 break;
39 default:
40 $(form).find(".additional_msg_div").css("visibility", "hidden");
41 return;
42 }
43 $(form).find(".additional_msg_div").css("visibility", "visible");
44
45
46 //loadmap.js
47 var map;
48 var infowindow = new google.maps.InfoWindow();
49
50 function initialization() {
51 showAllReports();
52 }
53
54 function showAllReports() {
55 $.ajax({
56 url: 'HttpServlet',
57 type: 'POST',
58 data: {
59 "tab_id": "1"
60 },
61 success: function(reports) {
62 mapInitialization(reports);
63 },
64 error: function(xhr, status, error) {
65 alert("An AJAX error occured: " + status + "\nError: " + error);
66 }
67 });
68 }
69
70 function mapInitialization(reports) {
71 var mapOptions = {
72 mapTypeId: google.maps.MapTypeId.ROADMAP, // Set the type of Map
73 };
74
75 // Render the map within the empty div
76 map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
77
78 var bounds = new google.maps.LatLngBounds();
79
80 $.each(reports, function(i, e) {
81 var long = Number(e['longitude']);
82 var lat = Number(e['latitude']);
83 var latlng = new google.maps.LatLng(lat, long);
84
85 bounds.extend(latlng);
86
87 // Create the infoWindow content
88 var contentStr = '<h4>Report Details</h4><hr>';
89 contentStr += '<p><b>' + 'Disaster' + ':</b>&nbsp' + e['disaster'] + '</p>';
90 contentStr += '<p><b>' + 'Report Type' + ':</b>&nbsp' + e['report_type'] +
91 '</p>';
92 if (e['report_type'] == 'request' || e['report_type'] == 'donation') {
93 contentStr += '<p><b>' + 'Resource Type' + ':</b>&nbsp' +
94 e['resource_type'] + '</p>';
95 } else if (e['report_type'] == 'damage') {
96 contentStr += '<p><b>' + 'Damage Type' + ':</b>&nbsp' + e['damage_type'] +
97 '</p>';
98 }
99 contentStr += '<p><b>' + 'Timestamp' + ':</b>&nbsp' +
100 e['time_stamp'].substring(0, 19) + '</p>';
101 if ('message' in e) {
102 contentStr += '<p><b>' + 'Message' + ':</b>&nbsp' + e['message'] + '</p>';
103 }
104
105 // Create the marker
106 var marker = new google.maps.Marker({ // Set the marker
107 position: latlng, // Position marker to coordinates
108 map: map, // assign the market to our map variable
109 customInfo: contentStr,
110 });
111
112 // Add a Click Listener to the marker
113 google.maps.event.addEventListener(marker, 'click', function() {
114 // use 'customInfo' to customize infoWindow
115 infowindow.setContent(marker['customInfo']);
116 infowindow.open(map, marker); // Open InfoWindow
117 });
118
119 });
120
121 map.fitBounds(bounds);
122
123 }
124
125
126 //Execute our 'initialization' function once the page has loaded.
127 google.maps.event.addDomListener(window, 'load', initialization);html,
128body {
129 background-color: #f5f5f5;
130}
131
132body {
133 padding-top: 50px;
134}
135
136.container-fluid,
137.row {
138 background-color: #f5f5f5;
139}
140
141.sidebar {
142 padding: 12px;
143 background-color: #f5f5f5;
144}
145
146form {
147 padding-top: 12px;
148}
149
150#map-canvas {
151 height: 100%;
152 position: absolute;
153 right: 0;
154}<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
155<html>
156
157<head>
158 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
159 <title>Web Project</title>
160
161 <!-- Custom styles -->
162 <link rel="stylesheet" href="css/style.css">
163
164 <!-- jQuery -->
165 <script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
166 <script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
167
168 <!-- Bootstrap -->
169 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
170 <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
171
172 <!-- Google Map js libraries -->
173 <script src="https://maps.googleapis.com/maps/api/js?&key=MY_API_KEY&libraries=places,visualization"></script>
174</head>
175
176<body>
177 <nav class="navbar navbar-inverse navbar-fixed-top">
178 <a class="navbar-brand">Disaster Management Portal</a>
179 </nav>
180
181 <div class="container-fluid">
182 <div class="row">
183 <div class="sidebar col-xs-3">
184
185 <!-- Tab Navis-->
186 <ul class="nav nav-tabs">
187 <li class="active"><a href="#create_report" data-toggle="tab">Create Report</a></li>
188 <li><a href="#query_report" data-toggle="tab">Query</a></li>
189 </ul>
190
191 <!-- Tab panes -->
192 <div class="tab-content ">
193 <!-- Create Report Tab Panel -->
194 <div class="tab-pane active" id="create_report">
195 <form id="create_report_form">
196 <div><label>First Name:&nbsp</label><input placeholder="Your first name" name="fN"></div>
197 <div><label>Last Name:&nbsp</label><input placeholder="Your last name" name="lN"></div>
198 <div>
199 <label><input type="radio" name="is_male" value="t">&nbspMale</label>
200 <label><input type="radio" name="is_male" value="f">&nbspFemale</label>
201 </div>
202 <div><label>Age:&nbsp</label><input placeholder="Your age" name="age"></div>
203 <div><label>Blood Type:</label>
204 <select name="blood_type">
205 <option value="">Choose your blood type</option>
206 <option value="A">A</option>
207 <option value="B">B</option>
208 <option value="O">O</option>
209 <option value="AB">AB</option>
210 <option value="Other">Other</option>
211 </select>
212 </div>
213 <div><label>Tel:&nbsp</label><input placeholder="Your telephone number" name="tel"></div>
214 <div><label>Email:&nbsp</label><input placeholder="Your email address" name="email"></div>
215 <div><label>Contact's First Name:&nbsp</label><input placeholder="Contact's first name" name="contact_fN"></div>
216 <div><label>Contact's Last Name:&nbsp</label><input placeholder="Contact's last name" name="contact_lN"></div>
217 <div><label>Contact's Tel:&nbsp</label><input placeholder="Contact's telephone number" name="contact_tel"></div>
218 <div><label>Contact's Email:&nbsp</label><input placeholder="Contact's email address" name="contact_email"></div>
219 <div><label>Report Type:</label>
220 <select onchange="onSelectReportType(this)" name="report_type">
221 <option value="">Choose the report type</option>
222 <option value="donation">Donation</option>
223 <option value="request">Request</option>
224 <option value="damage">Damage Report</option>
225 </select>
226 </div>
227 <div class="additional_msg_div" style="visibility: hidden"><label class="additional_msg"></label>
228 <select class="additional_msg_select" name="additional_message"></select>
229 </div>
230 <div><label>Disaster Type:</label>
231 <select name="disaster_type">
232 <option value="">Choose the disaster type</option>
233 <option value="flood">flood</option>
234 <option value="wildfire">wildfire</option>
235 <option value="earthquake">earthquake</option>
236 <option value="tornado">tornado</option>
237 <option value="hurricane">hurricane</option>
238 <option value="other">other</option>
239 </select>
240 </div>
241 <div><label>Address:</label>
242 <input id="autocomplete" placeholder="Address">
243 </div>
244 <div><label>Comment:&nbsp</label><input placeholder="Additional message" name="message"></div>
245 <button type="submit" class="btn btn-default" id="report_submit_btn">
246 <span class="glyphicon glyphicon-star"></span> Submit
247 </button>
248 </form>
249 </div>
250
251 <!-- Query Report Tab Panel -->
252 <div class="tab-pane" id="query_report">
253 <form id="query_report_form">
254 <div><label>Report Type:</label>
255 <select onchange="onSelectReportType(this)" name="report_type">
256 <option value="">Choose the report type</option>
257 <option value="donation">Donation</option>
258 <option value="request">Request</option>
259 <option value="damage">Damage Report</option>
260 </select>
261 </div>
262 <div class="additional_msg_div" style="visibility: hidden"><label class="additional_msg"></label>
263 <select class="additional_msg_select" name="resource_or_damage"></select>
264 </div>
265 <div><label>Disaster Type:</label>
266 <select name="disaster_type">
267 <option value="">Choose the disaster type</option>
268 <option value="flood">flood</option>
269 <option value="wildfire">wildfire</option>
270 <option value="earthquake">earthquake</option>
271 <option value="tornado">tornado</option>
272 <option value="hurricane">hurricane</option>
273 <option value="other">other</option>
274 </select>
275 </div>
276 <button type="submit" class="btn btn-default">
277 <span class="glyphicon glyphicon-star"></span> Submit the query
278 </button>
279 </form>
280 </div>
281 </div>
282 </div>
283
284 <div id="map-canvas" class="col-xs-9"></div>
285
286 </div>
287 </div>
288</body>
289
290</html>
ANSWER
Answered 2021-Nov-12 at 20:12Thank you Randy for the solution! I had to modify the example from the Google Maps documentation to match what the lab wanted but I figured it out. I included the infowindow.setContent(marker['customInfo']);
from my original code and changed my code to match the syntax from the documentation.
Here's the working code for the Click Listener:
1//loadform.js
2function onSelectReportType(ele) {
3 var form = $(ele).parent().parent();
4 var label = $(form).find(".additional_msg");
5 var select = $(form).find(".additional_msg_select");
6
7 switch (ele.value) {
8 case "donation":
9 case "request":
10 label.text("Resource Type:");
11 select.find('option').remove();
12 select.append($("<option></option>")
13 .attr("value", "")
14 .text("Choose the resource type"));
15 selectValues = ['water', 'food', 'money', 'medicine', 'cloth',
16 'rescue/volunteer'
17 ];
18 $.each(selectValues, function(index, value) {
19 select.append($("<option></option>")
20 .attr("value", value)
21 .text(value));
22 });
23 break;
24 case "damage":
25 label.text("Damage Type:");
26 select.find('option').remove();
27 select.append($("<option></option>")
28 .attr("value", "")
29 .text("Choose the damage type"));
30 selectValues = ['polution', 'building damage', 'road damage', 'casualty',
31 'other'
32 ];
33 $.each(selectValues, function(index, value) {
34 select.append($("<option></option>")
35 .attr("value", value)
36 .text(value));
37 });
38 break;
39 default:
40 $(form).find(".additional_msg_div").css("visibility", "hidden");
41 return;
42 }
43 $(form).find(".additional_msg_div").css("visibility", "visible");
44
45
46 //loadmap.js
47 var map;
48 var infowindow = new google.maps.InfoWindow();
49
50 function initialization() {
51 showAllReports();
52 }
53
54 function showAllReports() {
55 $.ajax({
56 url: 'HttpServlet',
57 type: 'POST',
58 data: {
59 "tab_id": "1"
60 },
61 success: function(reports) {
62 mapInitialization(reports);
63 },
64 error: function(xhr, status, error) {
65 alert("An AJAX error occured: " + status + "\nError: " + error);
66 }
67 });
68 }
69
70 function mapInitialization(reports) {
71 var mapOptions = {
72 mapTypeId: google.maps.MapTypeId.ROADMAP, // Set the type of Map
73 };
74
75 // Render the map within the empty div
76 map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
77
78 var bounds = new google.maps.LatLngBounds();
79
80 $.each(reports, function(i, e) {
81 var long = Number(e['longitude']);
82 var lat = Number(e['latitude']);
83 var latlng = new google.maps.LatLng(lat, long);
84
85 bounds.extend(latlng);
86
87 // Create the infoWindow content
88 var contentStr = '<h4>Report Details</h4><hr>';
89 contentStr += '<p><b>' + 'Disaster' + ':</b>&nbsp' + e['disaster'] + '</p>';
90 contentStr += '<p><b>' + 'Report Type' + ':</b>&nbsp' + e['report_type'] +
91 '</p>';
92 if (e['report_type'] == 'request' || e['report_type'] == 'donation') {
93 contentStr += '<p><b>' + 'Resource Type' + ':</b>&nbsp' +
94 e['resource_type'] + '</p>';
95 } else if (e['report_type'] == 'damage') {
96 contentStr += '<p><b>' + 'Damage Type' + ':</b>&nbsp' + e['damage_type'] +
97 '</p>';
98 }
99 contentStr += '<p><b>' + 'Timestamp' + ':</b>&nbsp' +
100 e['time_stamp'].substring(0, 19) + '</p>';
101 if ('message' in e) {
102 contentStr += '<p><b>' + 'Message' + ':</b>&nbsp' + e['message'] + '</p>';
103 }
104
105 // Create the marker
106 var marker = new google.maps.Marker({ // Set the marker
107 position: latlng, // Position marker to coordinates
108 map: map, // assign the market to our map variable
109 customInfo: contentStr,
110 });
111
112 // Add a Click Listener to the marker
113 google.maps.event.addEventListener(marker, 'click', function() {
114 // use 'customInfo' to customize infoWindow
115 infowindow.setContent(marker['customInfo']);
116 infowindow.open(map, marker); // Open InfoWindow
117 });
118
119 });
120
121 map.fitBounds(bounds);
122
123 }
124
125
126 //Execute our 'initialization' function once the page has loaded.
127 google.maps.event.addDomListener(window, 'load', initialization);html,
128body {
129 background-color: #f5f5f5;
130}
131
132body {
133 padding-top: 50px;
134}
135
136.container-fluid,
137.row {
138 background-color: #f5f5f5;
139}
140
141.sidebar {
142 padding: 12px;
143 background-color: #f5f5f5;
144}
145
146form {
147 padding-top: 12px;
148}
149
150#map-canvas {
151 height: 100%;
152 position: absolute;
153 right: 0;
154}<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
155<html>
156
157<head>
158 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
159 <title>Web Project</title>
160
161 <!-- Custom styles -->
162 <link rel="stylesheet" href="css/style.css">
163
164 <!-- jQuery -->
165 <script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
166 <script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
167
168 <!-- Bootstrap -->
169 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
170 <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
171
172 <!-- Google Map js libraries -->
173 <script src="https://maps.googleapis.com/maps/api/js?&key=MY_API_KEY&libraries=places,visualization"></script>
174</head>
175
176<body>
177 <nav class="navbar navbar-inverse navbar-fixed-top">
178 <a class="navbar-brand">Disaster Management Portal</a>
179 </nav>
180
181 <div class="container-fluid">
182 <div class="row">
183 <div class="sidebar col-xs-3">
184
185 <!-- Tab Navis-->
186 <ul class="nav nav-tabs">
187 <li class="active"><a href="#create_report" data-toggle="tab">Create Report</a></li>
188 <li><a href="#query_report" data-toggle="tab">Query</a></li>
189 </ul>
190
191 <!-- Tab panes -->
192 <div class="tab-content ">
193 <!-- Create Report Tab Panel -->
194 <div class="tab-pane active" id="create_report">
195 <form id="create_report_form">
196 <div><label>First Name:&nbsp</label><input placeholder="Your first name" name="fN"></div>
197 <div><label>Last Name:&nbsp</label><input placeholder="Your last name" name="lN"></div>
198 <div>
199 <label><input type="radio" name="is_male" value="t">&nbspMale</label>
200 <label><input type="radio" name="is_male" value="f">&nbspFemale</label>
201 </div>
202 <div><label>Age:&nbsp</label><input placeholder="Your age" name="age"></div>
203 <div><label>Blood Type:</label>
204 <select name="blood_type">
205 <option value="">Choose your blood type</option>
206 <option value="A">A</option>
207 <option value="B">B</option>
208 <option value="O">O</option>
209 <option value="AB">AB</option>
210 <option value="Other">Other</option>
211 </select>
212 </div>
213 <div><label>Tel:&nbsp</label><input placeholder="Your telephone number" name="tel"></div>
214 <div><label>Email:&nbsp</label><input placeholder="Your email address" name="email"></div>
215 <div><label>Contact's First Name:&nbsp</label><input placeholder="Contact's first name" name="contact_fN"></div>
216 <div><label>Contact's Last Name:&nbsp</label><input placeholder="Contact's last name" name="contact_lN"></div>
217 <div><label>Contact's Tel:&nbsp</label><input placeholder="Contact's telephone number" name="contact_tel"></div>
218 <div><label>Contact's Email:&nbsp</label><input placeholder="Contact's email address" name="contact_email"></div>
219 <div><label>Report Type:</label>
220 <select onchange="onSelectReportType(this)" name="report_type">
221 <option value="">Choose the report type</option>
222 <option value="donation">Donation</option>
223 <option value="request">Request</option>
224 <option value="damage">Damage Report</option>
225 </select>
226 </div>
227 <div class="additional_msg_div" style="visibility: hidden"><label class="additional_msg"></label>
228 <select class="additional_msg_select" name="additional_message"></select>
229 </div>
230 <div><label>Disaster Type:</label>
231 <select name="disaster_type">
232 <option value="">Choose the disaster type</option>
233 <option value="flood">flood</option>
234 <option value="wildfire">wildfire</option>
235 <option value="earthquake">earthquake</option>
236 <option value="tornado">tornado</option>
237 <option value="hurricane">hurricane</option>
238 <option value="other">other</option>
239 </select>
240 </div>
241 <div><label>Address:</label>
242 <input id="autocomplete" placeholder="Address">
243 </div>
244 <div><label>Comment:&nbsp</label><input placeholder="Additional message" name="message"></div>
245 <button type="submit" class="btn btn-default" id="report_submit_btn">
246 <span class="glyphicon glyphicon-star"></span> Submit
247 </button>
248 </form>
249 </div>
250
251 <!-- Query Report Tab Panel -->
252 <div class="tab-pane" id="query_report">
253 <form id="query_report_form">
254 <div><label>Report Type:</label>
255 <select onchange="onSelectReportType(this)" name="report_type">
256 <option value="">Choose the report type</option>
257 <option value="donation">Donation</option>
258 <option value="request">Request</option>
259 <option value="damage">Damage Report</option>
260 </select>
261 </div>
262 <div class="additional_msg_div" style="visibility: hidden"><label class="additional_msg"></label>
263 <select class="additional_msg_select" name="resource_or_damage"></select>
264 </div>
265 <div><label>Disaster Type:</label>
266 <select name="disaster_type">
267 <option value="">Choose the disaster type</option>
268 <option value="flood">flood</option>
269 <option value="wildfire">wildfire</option>
270 <option value="earthquake">earthquake</option>
271 <option value="tornado">tornado</option>
272 <option value="hurricane">hurricane</option>
273 <option value="other">other</option>
274 </select>
275 </div>
276 <button type="submit" class="btn btn-default">
277 <span class="glyphicon glyphicon-star"></span> Submit the query
278 </button>
279 </form>
280 </div>
281 </div>
282 </div>
283
284 <div id="map-canvas" class="col-xs-9"></div>
285
286 </div>
287 </div>
288</body>
289
290</html> // Add a Click Listener to the marker
291 marker.addListener('click', () => {
292 infowindow.setContent(marker['customInfo']);
293 infowindow.open({
294 anchor: marker,
295 map,
296 shouldFocus: false,
297 });
298 });
299
QUESTION
How to define two different entity roles for the same prebuilt Entity (number) in LUIS
Asked 2021-Nov-10 at 12:54I am looking to build a bot that typically requires two numbers with a different meaning (role) in the same utterance. Let's take the example of a StockMarket order assistent (fictional, as example)
Some example utterances:
Buy 100 MSFT stock at limit of 340
Get me 200 Apple at maximum 239.4
Buy 40 AMZN at market price
In LUIS portal, I have defined two entities
StockSymbol
a List entity (for all stocks, linking their symbols and the names as synonyms).number
the prebuilt entity with two Roles:Amount
andLimit
When specifying the utterances shown as example, it shows that the entities get recognized. But I cannot find a way to specify the roles for the different number entities in my sample utterances. (in the examples, the first number instance of number is the Amount, and if a second it there, that is typically the Limit role.
Anyone an idea on how to define this and set this up?
Best regards
ANSWER
Answered 2021-Nov-10 at 12:54There are 2 different ways to do this, First is to use roles for a prebuilt entity, go into the number prebuilt, click on Roles, add 2 different roles.
one for Amount another for Limit then you have to go in the utterances and label for the roles, you do that by going to the utterance, clicking on the @ symbol on the right, selecting the number prebuilt, selecting the role, then highlighting the numbers with that role.
Second approach is to use ML entities, create 2 ML entities, one for Amount one for Limit. Add the number as a feature and make it a required feature, and then go ahead and label the Amounts with the Amount entity and the limits with the Limit entity directly.
QUESTION
HTTPS in Nodejs - error:06065064 digital envelope routines evp_decryptfinal_ex bad decrypt
Asked 2021-Oct-21 at 08:33We tried to install our Hapis (Nodejs Version 14) Web service on our customer's server. It ran under HTTP for months, but when we went to enable HTTPS with the appropriate paths to the cert and key it fails when the service starts up with:
error:06065064:digital envelope routines:EVP_Decryptfinal_ex:bad decrypt
Their certificate and key are generated using the Venafi online portal. It gave them a crt and key. The crt uses a Signature algorithm: sha256RSA, Signature hash algorithm of sha256, and Thumbprint algorith: sha1.
Also, the private key is a RSA PRIVATE KEY with Proc-Type: 4,ENCRYPTED and DEK-Info: DES-EDE3-CBC.
I am not sure what is going on, because HTTPS works fine on our development servers.
- Is the problem in HapiJS?
- Is the problem with the certificate or key themselves?
- Is there an Node option I need to be passing in when creating the service?
Please help.
ANSWER
Answered 2021-Aug-21 at 05:00The specified error 06065064:digital envelope routines:EVP_Decryptfinal_ex:bad decrypt
occurs in an SSL/TLS connection using OpenSSL (which is what nodejs modules like tls and https actually use) when the privatekey is encrypted (with a passphrase) and the correct passphrase is not provided to decrypt it. The described file format, beginning with a line -----BEGIN RSA PRIVATE KEY-----
followed by lines Proc-Type:
and DEK-Info:
is indeed one of the encrypted formats used by OpenSSL. Specifically this is the encrypted 'traditional' or 'legacy' format; the PKSC8 format added about 2000 but still considered new(!) uses -----BEGIN ENCRYPTED PRIVATE KEY-----
and no 822-style headers, only base64 (of the encrypted structure defined by PKCS8); see ursinely-verbose https://security.stackexchange.com/questions/39279/stronger-encryption-for-ssh-keys/#52564 about OpenSSH's use of OpenSSL, which is basically the same as nodejs's use.
The tls
module and others that build on it including https
ultimately read the key(s) and cert(s) using tls.createSecureContext
which accepts in options
a member passphrase
, or if you need to use multiple keys (and certs) you can provide a passphrase for each key as described in the linked doc.
Alternatively you can avoid the need for a passphrase by converting the key to an unencrypted file, if acceptable under applicable security policies and regulations. (Good policies may prohibit this, but they usually also prohibit getting the privatekey from or providing it to any other system, especially one 'online' somewhere, and your customer is doing the latter.) To retain traditional format do
1openssl rsa -in oldfile -out newfile
2# and give the passphrase when prompted, or see the man page about -passin
3
or you can use the 'new' PKCS8 format with
1openssl rsa -in oldfile -out newfile
2# and give the passphrase when prompted, or see the man page about -passin
3openssl pkey -in oldfile -out newfile
4# technically only in release 1.0.0 up, but pretty much everyone is there now
5#
6# or in all versions back to about 2000
7openssl pkcs8 -topk8 -nocrypt -in oldfile -out newfile
8
Community Discussions contain sources that include Stack Exchange Network
Tutorials and Learning Resources in Portal
Tutorials and Learning Resources are not available at this moment for Portal