1515package auth
1616
1717import (
18+ "errors"
1819 "maps"
1920 "strings"
2021
@@ -33,6 +34,8 @@ var tokenMarshaler = protojson.MarshalOptions{
3334 EmitDefaultValues : false ,
3435}
3536
37+ var ErrSensitiveCredentials = errors .New ("room configuration should not contain sensitive credentials" )
38+
3639func (c * RoomConfiguration ) Clone () * RoomConfiguration {
3740 if c == nil {
3841 return nil
@@ -48,6 +51,116 @@ func (c *RoomConfiguration) UnmarshalJSON(data []byte) error {
4851 return protojson .Unmarshal (data , (* livekit .RoomConfiguration )(c ))
4952}
5053
54+ // CheckCredentials checks if the room configuration contains sensitive credentials
55+ // and returns an error if it does.
56+ //
57+ // This is used to prevent sensitive credentials from being leaked to the client.
58+ // It is not used to validate the credentials themselves, as that is done by the
59+ // egress service.
60+ func (c * RoomConfiguration ) CheckCredentials () error {
61+ if c .Egress == nil {
62+ return nil
63+ }
64+
65+ if c .Egress .Participant != nil {
66+ for _ , output := range c .Egress .Participant .FileOutputs {
67+ if err := checkOutputForCredentials (output .Output ); err != nil {
68+ return err
69+ }
70+ }
71+ for _ , output := range c .Egress .Participant .SegmentOutputs {
72+ if err := checkOutputForCredentials (output .Output ); err != nil {
73+ return err
74+ }
75+ }
76+ }
77+ if c .Egress .Room != nil {
78+ for _ , output := range c .Egress .Room .FileOutputs {
79+ if err := checkOutputForCredentials (output .Output ); err != nil {
80+ return err
81+ }
82+ }
83+ for _ , output := range c .Egress .Room .SegmentOutputs {
84+ if err := checkOutputForCredentials (output .Output ); err != nil {
85+ return err
86+ }
87+ }
88+ for _ , output := range c .Egress .Room .ImageOutputs {
89+ if err := checkOutputForCredentials (output .Output ); err != nil {
90+ return err
91+ }
92+ }
93+ if len (c .Egress .Room .StreamOutputs ) > 0 {
94+ // do not leak stream key
95+ return ErrSensitiveCredentials
96+ }
97+ }
98+ if c .Egress .Tracks != nil {
99+ if err := checkOutputForCredentials (c .Egress .Tracks .Output ); err != nil {
100+ return err
101+ }
102+ }
103+ return nil
104+ }
105+
106+ func checkOutputForCredentials (output any ) error {
107+ if output == nil {
108+ return nil
109+ }
110+
111+ switch msg := output .(type ) {
112+ case * livekit.EncodedFileOutput_S3 :
113+ if msg .S3 .Secret != "" {
114+ return ErrSensitiveCredentials
115+ }
116+ case * livekit.SegmentedFileOutput_S3 :
117+ if msg .S3 .Secret != "" {
118+ return ErrSensitiveCredentials
119+ }
120+ case * livekit.AutoTrackEgress_S3 :
121+ if msg .S3 .Secret != "" {
122+ return ErrSensitiveCredentials
123+ }
124+ case * livekit.EncodedFileOutput_Gcp :
125+ if msg .Gcp .Credentials != "" {
126+ return ErrSensitiveCredentials
127+ }
128+ case * livekit.SegmentedFileOutput_Gcp :
129+ if msg .Gcp .Credentials != "" {
130+ return ErrSensitiveCredentials
131+ }
132+ case * livekit.AutoTrackEgress_Gcp :
133+ if msg .Gcp .Credentials != "" {
134+ return ErrSensitiveCredentials
135+ }
136+ case * livekit.EncodedFileOutput_Azure :
137+ if msg .Azure .AccountKey != "" {
138+ return ErrSensitiveCredentials
139+ }
140+ case * livekit.SegmentedFileOutput_Azure :
141+ if msg .Azure .AccountKey != "" {
142+ return ErrSensitiveCredentials
143+ }
144+ case * livekit.AutoTrackEgress_Azure :
145+ if msg .Azure .AccountKey != "" {
146+ return ErrSensitiveCredentials
147+ }
148+ case * livekit.EncodedFileOutput_AliOSS :
149+ if msg .AliOSS .Secret != "" {
150+ return ErrSensitiveCredentials
151+ }
152+ case * livekit.SegmentedFileOutput_AliOSS :
153+ if msg .AliOSS .Secret != "" {
154+ return ErrSensitiveCredentials
155+ }
156+ case * livekit.AutoTrackEgress_AliOSS :
157+ if msg .AliOSS .Secret != "" {
158+ return ErrSensitiveCredentials
159+ }
160+ }
161+ return nil
162+ }
163+
51164type ClaimGrants struct {
52165 Identity string `json:"-"`
53166 Name string `json:"name,omitempty"`
0 commit comments