您如何向潜在客户和现有客户教授技术性很强的主题?如何让旅途顺利?
在 Isovalent,我们热衷于为用户提供尽可能无缝的学习体验。 Isovalent 是 Cilium 的创建者,Cilium 是事实上的 Kubernetes 云网络平台。虽然我们热爱网络和安全,但我们很高兴人们可能会觉得这是一个困难的话题。我们认为我们会让学习 Kubernetes 网络变得有趣,因此我们将学习体验游戏化。
Instruqt 提供了一个很棒的平台来构建实践实验室,该实验室既具有先进的技术,又对用户有吸引力。
我们还相信用户体验应该流畅并且流程应该完全自动化。
幸运的是,利用 Instruqt graphQL API 可以做很多事情。
为此,我们编写了自己的 instruqt-go 库,并决定将其开源。该库旨在帮助开发人员轻松实现自动化并与 Instruqt 平台集成。
发布 Instruqt 实验室的问题之一是将 Instruqt 中的用户信息与您自己的数据库或 CRM 的用户信息链接起来。
在第一篇文章中,我们将指导您使用 instruqt-go 构建代理:
- 收集用户标识符(例如 HubSpot 代币);
- 验证用户身份;
- 将用户重定向到具有通过 Instruqt API 生成的唯一访问令牌的实验室。
然后我们将在 Google Cloud Functions 上发布该函数。
为什么需要代理
在实验室收集用户信息的原因有多种:
- 完成实验后能够生成徽章(我们喜欢徽章)非常有用(在以后的帖子中会详细介绍)。
- 它可以向用户展示他们在实验室中的进度,以便他们知道要进行哪些实验(例如参见 Cilium 实验室地图)。
如何传递用户数据
有多种方法可以将用户数据传递到 Instruqt 轨道。
自定义参数
Instruqt 自定义参数对于在启动曲目时传递任何类型的信息非常有用。这些字段只是作为查询参数添加到 URL,并以 icp_ 为前缀。这些参数还可以在 Instruqt webhooks 以及 Instruqt GraphQL API 中检索,使其实用起来。
直到最近,Instruqt 还鼓励赛道开发人员使用自定义参数传递用户信息(例如姓名、电子邮件或令牌)。
但是,使用自定义参数有一些缺点:
- 它们没有标准化,Instruqt 不会解释它们。这意味着用户会话将在 Instruqt 报告中显示为匿名(并且唯一用户计数可能是错误的)。
- 默认情况下它们不加密。您当然可以使用自己的密钥对它们进行加密,但 Instruqt 会在播放报告中向您显示加密的值。
- 我多次看到当用户重新启动实验室时自定义参数丢失。我实际上启动了自己的缓存数据库来解决这个问题。
邀请
Instruqt 邀请允许创建曲目列表并生成可与用户共享以便于访问的邀请链接。邀请可以设置为通过表单收集用户数据。
然后,此用户数据将添加到 Instruqt 上的用户详细信息中(用户详细信息附加到用户帐户,但每个 Instruqt 团队都是唯一的)。
这对于研讨会来说非常实用,但也有一些限制:
- 使用邀请访问所有实验室意味着邀请必须包含所有已发布的实验室。
- 邀请有自己的登陆页面,因此它不适用于我们的 Cilium Labs 地图或其他信息亭方法。
注意:Instruqt 最近推出了登陆页面,这是一种邀请形式,可以调整登陆页面,具有相同的优点和限制。
第三方表格
最近,Instruqt 添加了另一种传递用户信息的方式,它结合了之前两种方法的优点。
加密的 PII 方法允许将 pii_tpg 查询参数传递到嵌入 URL。这意味着:
- 数据使用 Instruqt 提供的公钥进行加密,因此 URL 不包含可读的用户信息。
- Instruqt 理解 pii_tpg 数据并拥有解密它的私钥。该信息用于填写用户的详细信息,就像他们接受了邀请一样。
- 这不链接到邀请,因此它可以与任何曲目一起使用。
我们将在本例中使用这种新方法,因为它是当今最通用的以安全可靠的方式向 Instruqt 传递信息的方法。
关于嵌入令牌的注释
当您访问 Instruqt 上的曲目页面时,可以选择嵌入曲目。
这将为您提供一个 URL,其中包含该曲目独有的令牌。
虽然使用该 URL 是完全有效的,但这也意味着任何有权访问此令牌的人都可以随时开始曲目。
Instruqt 最近添加了一个 API 调用来为曲目生成一次性令牌,这样使用此类令牌的 URL 只能使用一次。
我们正在编码的代理将使用一次性令牌,因为我们可以访问 API 并且可以轻松生成它们。
创建代理
初始步骤
首先,为您的函数创建一个目录:
mkdir instruqt-proxy
移动到该目录并初始化Go环境:
# Replace example.com with the prefix of your choice go mod init example.com/labs
谷歌云功能利用
对于本地测试,创建一个cmd目录:
mkdir cmd
在该目录中创建一个 main.go 文件,内容如下:
package main import ( "log" "os" // Blank-import the function package so the init() runs // Adapt if you replaced example.com earlier _ "example.com/labs" "github.com/GoogleCloudPlatform/functions-framework-go/funcframework" ) func main() { // Use PORT environment variable, or default to 8080. port := "8080" if envPort := os.Getenv("PORT"); envPort != "" { port = envPort } if err := funcframework.Start(port); err != nil { log.Fatalf("funcframework.Start: %v\n", err) } }
创建函数
返回 instruqt-proxy 目录,创建一个 proxy.go 文件,然后向其中添加 init() 函数以及我们将使用的 Go 包:
package labs import ( "fmt" "net/http" "net/url" "os" "github.com/GoogleCloudPlatform/functions-framework-go/functions" "github.com/isovalent/instruqt-go/instruqt" ) func init() { functions.HTTP("InstruqtProxy", instruqtProxy) }
这将允许 Google Cloud Functions 在初始化时调用 instruqtProxy 函数。
让我们编写该函数:
const ( // Replace team name with yours instruqtTeam = "isovalent" ) func instruqtProxy(w http.ResponseWriter, r *http.Request) { instruqtToken := os.Getenv("INSTRUQT_TOKEN") if instruqtToken == "" { w.WriteHeader(http.StatusInternalServerError) return } instruqtClient := instruqt.NewClient(instruqtToken, instruqtTeam) // Get user from passed token utk := r.URL.Query().Get("utk") if utk == "" { w.WriteHeader(http.StatusUnauthorized) return } user, err := getUser(utk) if err != nil { w.WriteHeader(http.StatusUnauthorized) return } labSlug := r.URL.Query().Get("slug") url, err := getLabURL(instruqtClient, user, labSlug) if err != nil { w.WriteHeader(http.StatusNotFound) return } http.Redirect(w, r, url, http.StatusFound) }
在此函数中,我们:
- 从 INSTRUQT_TOKEN 环境变量获取 Instruqt 令牌
- 为令牌和团队初始化 Instruqt API 客户端
- 从 URL 参数中检索 utk 参数以验证用户
- 根据该UTK获取用户信息
- 从 URL 参数获取 lab slug
- 检索重定向的实验室 URL
- 使用 http.Redirect 函数重定向用户
实现 getLabURL()
getLabURL 函数将根据用户信息、请求的实验室 slug 以及来自 Instruqt API 的动态信息生成实验室的重定向 URL。
我们来写吧:
const ( // Replace with your sign-up page format labSignupPage = "https://isovalent.com/labs/%s" // Adapt to your values finishBtnText = "Try your next Lab!" finishBtnURL = "https://labs-map.isovalent.com/map?lab=%s&showInfo=true" ) func getLabURL(instruqtClient *instruqt.Client, u user, slug string) (string, error) { track, err := instruqtClient.GetTrackBySlug(slug) if err != nil { return "", err } // Unknown user if u.Email == "" { url := fmt.Sprintf(labSignupPage, slug) return url, nil } // Get one-time token token, err := instruqtClient.GenerateOneTimePlayToken(track.Id) if err != nil { return "", err } labURL, err := url.Parse(fmt.Sprintf("https://play.instruqt.com/embed/%s/tracks/%s", instruqtTeam, track.Slug)) if err != nil { return "", err } // Prepare the fields to encrypt encryptedPII, err := instruqtClient.EncryptUserPII(u.FirstName, u.LastName, u.Email) if err != nil { return "", err } // Add params params := map[string]string{ "token": token, "pii_tpg": encryptedPII, "show_challenges": "true", "finish_btn_target": "_blank", "finish_btn_text": finishBtnText, "finish_btn_url": fmt.Sprintf(finishBtnURL, track.Slug), } q := labURL.Query() for key, value := range params { q.Set(key, value) } // Encode the parameters labURL.RawQuery = q.Encode() return labURL.String(), nil }
首先,请注意,我们定义了一些您可以调整的新常量:
- labSignupPage 是您网站上的 URL,未经身份验证的用户将被重定向到该 URL。它包含实验室蛞蝓的变量。
- finishBtnText 是实验室完成按钮上显示的文本。
- finishBtnURL 是实验结束时按钮的操作。它还包含实验室蛞蝓的变量。
现在我们来解释一下getLabURL()函数的步骤:
- 从Instruqt API中获取曲目信息,如果找不到则报错。
- 如果用户未知,则重定向到注册页面。
- 为嵌入式轨道访问生成一次性令牌。
- 生成重定向 URL。
- 使用 Instruqt API 中的 PII 密钥加密用户信息。
- 将所有参数(一次性令牌、加密的用户信息、完成按钮选项)添加到重定向 URL。
- 对 URL 进行编码。
- 返回结果 URL。
getUser() 函数
此代理中缺少的最后一个部分是 getUser() 函数。我在这里帮不了你太多,因为这部分是你插入你自己的逻辑的地方。您可能正在使用像 Hubspot 这样的 CRM 从 UTK 或其他数据库检索联系信息,这取决于您!
我将在此处向您展示的代码仅返回示例用户:
/* * This is where you add the logic to get user information from your CRM/database. */ type user struct { FirstName string LastName string Email string } func getUser(utk string) (u user, err error) { // Implement the logic to get your user information from UTK u = user{ FirstName: "John", LastName: "Doe", Email: "john@doe.com", } return u, err }
测试代码
现在我们已经有了完整的 proxy.go 功能,让我们测试一下!
首先,使用以下内容更新您的 go.mod 和 go.sum 文件:
go get ./... go mod tidy
在 Instruqt 仪表板中,转到“API 密钥”并获取 API 密钥的值。将其导出为 shell 中的变量:
export INSTRUQT_TOKEN=<your_instruqt_token> </your_instruqt_token>
接下来,在本地计算机上启动该功能:
FUNCTION_TARGET=InstruqtProxy go run ./cmd/main.go
最后,在另一个终端中,向 localhost:8080 发出测试请求,您的函数将在其中运行(如果需要,您可以传递上面的 PORT 环境变量来更改端口):
curl -i "localhost:8080/?slug=cilium-getting-started&utk=someUtkValue"
适应使用 Instruqt 组织中存在的轨道 slug。如果该曲目存在,您应该会收到一个 302 响应,其中包含用于访问的一次性令牌的重定向 URL,以及使用 PII 密钥加密的 John Doe 的信息和一次性令牌(以 ott_ 开头)!
替代测试:使用 Docker
如果您想使用 Docker 在本地测试您的功能,您可以在当前目录中创建一个 Dockerfile:
FROM golang:1.23 WORKDIR /app COPY . . RUN go build -o myapp ./cmd/main.go ENV DEV=true ENV PORT=8080 EXPOSE $PORT CMD ["./myapp"]
添加 docker-compose.yaml 文件:
version: '3' services: proxy: build: ./ ports: - "8080:8080" environment: INSTRUQT_TOKEN: ${INSTRUQT_TOKEN} FUNCTION_TARGET: InstruqtProxy
最后,构建并启动您的容器:
docker-compose up --build
并且您可以像以前一样向 localhost:8080 发送请求!
Hosting the Proxy on Google Cloud Functions
In order to deploy to Google Cloud, first make sure you are logged in to your Google Cloud project:
gcloud auth application-default login
Create a Secret for the API Token
Next, let's create a new secret for the Instruqt token:
echo -n "$INSTRUQT_TOKEN" | gcloud secrets create instruqt-token --data-file=-
In order to adjust the permissions on this secret, you will need to get your project ID:
PROJECT_NUMBER=$(gcloud projects describe $(gcloud config get-value project) --format="value(projectNumber)")
Then, add the "Secret Manager Secret Accessor" role for the default Compute Engine service account for the project:
gcloud secrets add-iam-policy-binding instruqt-token \ --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \ --role="roles/secretmanager.secretAccessor"
Your secret is now ready to be used by the function!
Deploy the Function
You can then deploy the function (adapt the region if needed):
gcloud functions deploy "instruqt-proxy" \ --gen2 --runtime=go122 --region=europe-west1 --source=. \ --entry-point="InstruqtProxy" --trigger-http --allow-unauthenticated \ --set-secrets="INSTRUQT_TOKEN=instruqt-token:latest"
This will upload and build your project, and return the URL to access the function.
This URL will look something like https://europe-west1-
You can then test the function using that URL instead of localhost:8080!
Further Considerations
This is a simplified approach to the lab proxy we use at Isovalent. There are things you might want to consider with this implementation:
- If you have actual user (instead of marketing contact), switch to a proper authentication system (e.g. JWT) instead of UTK.
- The current implementation will give access to any lab in your collection if you know its slug. You might want to filter them out (using for example track tags).
- This implementation manages errors but is very basic in logging. We would recommend using Google Cloud logging to easily audit function runs.
- You might want to pass extra information as custom parameters. For example, we like to pass some form of even or campaign ID. These can then be retrieved via the API as part or the Track structure.
- If you're using a custom form and redirecting to the proxy, you might want to be sure your CRM/database has already gotten the user information. You can for example implement a retry logic in the proxy function.
- Invite embed URLs contain the invite ID. If you want to support invites, the proxy could take an optional invite parameter and add it to the URL.
Using the Proxy
This proxy can typically be used to give access to authenticated users in a safe way, while preserving user information in Instruqt reports and making sure embed URLs are not reusable.
Here is an example of usage of this proxy:
- Set up lab sign-up pages with the form system of your choice (e.g. using Hubspot forms).
- Retrieve a user identifier from the page context (e.g. a Hubspot cookie token).
- Redirect users to the proxy, passing the user identifier and lab slug as parameters.
This can allow you to build a series of public sign-up pages for your labs, similar to what we have built on the Isovalent website. It can also be used to build a Kiosk interface, or even a more creative landing page such as the Cilium Labs map, where clicks on the map redirect to the lab proxy.
By making a complex networking technology like Cilium fun with our labs, we have made it the experience for users less intimidating and more approachable. Using our proxy can help you provide a similar user experience to your prospects. Please get in touch if you have any questions.
以上是简化对嵌入式 Instruqt 实验室的访问的详细内容。更多信息请关注PHP中文网其他相关文章!

掌握Go语言中的strings包可以提高文本处理能力和开发效率。1)使用Contains函数检查子字符串,2)用Index函数查找子字符串位置,3)Join函数高效拼接字符串切片,4)Replace函数替换子字符串。注意避免常见错误,如未检查空字符串和大字符串操作性能问题。

你应该关心Go语言中的strings包,因为它能简化字符串操作,使代码更清晰高效。1)使用strings.Join高效拼接字符串;2)用strings.Fields按空白符分割字符串;3)通过strings.Index和strings.LastIndex查找子串位置;4)用strings.ReplaceAll进行字符串替换;5)利用strings.Builder进行高效字符串拼接;6)始终验证输入以避免意外结果。

thestringspackageingoisesential forefficientstringManipulation.1)itoffersSimpleyetpoperfulfunctionsFortaskSlikeCheckingSslingSubstringsStringStringsStringsandStringsN.2)ithandhishiCodeDewell,withFunctionsLikestrings.fieldsfieldsfieldsfordsforeflikester.fieldsfordsforwhitespace-fieldsforwhitespace-separatedvalues.3)3)

WhendecidingbetweenGo'sbytespackageandstringspackage,usebytes.Bufferforbinarydataandstrings.Builderforstringoperations.1)Usebytes.Bufferforworkingwithbyteslices,binarydata,appendingdifferentdatatypes,andwritingtoio.Writer.2)Usestrings.Builderforstrin

Go的strings包提供了多种字符串操作功能。1)使用strings.Contains检查子字符串。2)用strings.Split将字符串分割成子字符串切片。3)通过strings.Join合并字符串。4)用strings.TrimSpace或strings.Trim去除字符串首尾的空白或指定字符。5)用strings.ReplaceAll替换所有指定子字符串。6)使用strings.HasPrefix或strings.HasSuffix检查字符串的前缀或后缀。

使用Go语言的strings包可以提升代码质量。1)使用strings.Join()优雅地连接字符串数组,避免性能开销。2)结合strings.Split()和strings.Contains()处理文本,注意大小写敏感问题。3)避免滥用strings.Replace(),考虑使用正则表达式进行大量替换。4)使用strings.Builder提高频繁拼接字符串的性能。

Go的bytes包提供了多种实用的函数来处理字节切片。1.bytes.Contains用于检查字节切片是否包含特定序列。2.bytes.Split用于将字节切片分割成smallerpieces。3.bytes.Join用于将多个字节切片连接成一个。4.bytes.TrimSpace用于去除字节切片的前后空白。5.bytes.Equal用于比较两个字节切片是否相等。6.bytes.Index用于查找子切片在largerslice中的起始索引。

theEncoding/binarypackageingoisesenebecapeitProvidesAstandArdArdArdArdArdArdArdArdAndWriteBinaryData,确保Cross-cross-platformCompatibilitiational and handhandlingdifferentendenness.itoffersfunctionslikeread,写下,写,dearte,readuvarint,andwriteuvarint,andWriteuvarIntforPreciseControloverBinary


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

Atom编辑器mac版下载
最流行的的开源编辑器

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境